From 877777d77690d741c93404fd176da7f5327c2878 Mon Sep 17 00:00:00 2001 From: 3chas3 Date: Tue, 31 Jan 2017 08:21:15 -0500 Subject: [PATCH] util-lib: Fix chase_symlinks() with absolute symlinks (#5185) If chase_symlinks() encouters an absolute symlink, it resets the todo buffer to just the newly discovered symlink and discards any of the remaining previous symlink path. Regardless of whether or not the symlink is absolute or relative, we need to preserve the remainder of the path that has not yet been resolved. --- src/basic/fs-util.c | 27 ++++++++++++--------------- src/test/test-fs-util.c | 7 +++++++ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index e31fa2711a..8fe19ee4e4 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -723,6 +723,8 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return -errno; if (S_ISLNK(st.st_mode)) { + char *joined; + _cleanup_free_ char *destination = NULL; /* This is a symlink, in this case read the destination. But let's make sure we don't follow @@ -746,9 +748,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (fd < 0) return -errno; - free_and_replace(buffer, destination); - - todo = buffer; free(done); /* Note that we do not revalidate the root, we take it as is. */ @@ -760,20 +759,18 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return -ENOMEM; } - } else { - char *joined; - - /* A relative destination. If so, this is what we'll prefix what's left to do with what - * we just read, and start the loop again, but remain in the current directory. */ - - joined = strjoin("/", destination, todo); - if (!joined) - return -ENOMEM; - - free(buffer); - todo = buffer = joined; } + /* Prefix what's left to do with what we just read, and start the loop again, + * but remain in the current directory. */ + + joined = strjoin("/", destination, todo); + if (!joined) + return -ENOMEM; + + free(buffer); + todo = buffer = joined; + continue; } diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index ae68587be9..4cb465d0d2 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -186,6 +186,13 @@ static void test_chase_symlinks(void) { r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result); assert_se(r == -ENOENT); + p = strjoina(temp, "/target"); + q = strjoina(temp, "/top"); + assert_se(symlink(q, p) >= 0); + p = strjoina(temp, "/target/idontexist"); + r = chase_symlinks(p, NULL, 0, &result); + assert_se(r == -ENOENT); + assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); }