X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbasic%2Ffs-util.c;fp=src%2Fbasic%2Ffs-util.c;h=be4c6a9faf41343f46a710ea827b33edfc18b0b1;hb=62383061a34dc8233b3e26c49271d5cb43fcb0f6;hp=e47b050b0dd95c0239d89a8fa39fadeca845cf94;hpb=8036e4d0b9ef0990597196155fe6fc6329a6a881;p=elogind.git diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index e47b050b0..be4c6a9fa 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -607,6 +607,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL; _cleanup_close_ int fd = -1; unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */ + bool exists = true; char *todo; int r; @@ -712,8 +713,25 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, /* Otherwise let's see what this is. */ child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH); - if (child < 0) + if (child < 0) { + + if (errno == ENOENT && + (flags & CHASE_NON_EXISTING) && + (isempty(todo) || path_is_safe(todo))) { + + /* If CHASE_NON_EXISTING is set, and the path does not exist, then that's OK, return + * what we got so far. But don't allow this if the remaining path contains "../ or "./" + * or something else weird. */ + + if (!strextend(&done, first, todo, NULL)) + return -ENOMEM; + + exists = false; + break; + } + return -errno; + } if (fstat(child, &st) < 0) return -errno; @@ -798,6 +816,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, *ret = done; done = NULL; - return 0; + return exists; } #endif // 0