diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-01-06 13:49:09 +0100 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-02-07 16:36:54 +0100 |
commit | c677e13c35ff2d475199bcc9432892396485b6b8 (patch) | |
tree | 0b51f16336f4ea95400a1e2647c062f1d740d190 /src/test | |
parent | Merge pull request #26324 from yuwata/argv-util-update-short-name (diff) | |
download | systemd-c677e13c35ff2d475199bcc9432892396485b6b8.tar.xz systemd-c677e13c35ff2d475199bcc9432892396485b6b8.zip |
chase-symlinks: chase_symlinks_at() AT_FDCWD fixes
- Whether we should return an absolute path or not is irrelevant
to whether CHASE_AT_RESOLVE_IN_ROOT is set. We should only return
an absolute path if we are provided one and the directory file
descriptor is AT_FDCWD
- When the directory file descriptor is AT_FDCWD, we should always
resolve symlinks against "/". Currently, if the directory file
descriptor is AT_FDCWD and CHASE_AT_RESOLVE_IN_ROOT is set, we
resolve symlinks against the current working directory which is
almost always not going to be what the caller wants.
- Currently, if we provide an absolute path with a positive directory
file descriptor without CHASE_AT_RESOLVE_IN_ROOT SET, we interpret
the path relative to "/" instead of the given directory file descriptor.
Let's make sure that when we're given a positive directory file
descriptor, we always resolve the given path relative to it.
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/test-fs-util.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 668a44733b..3fc5f88d26 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -430,6 +430,42 @@ TEST(chase_symlinks) { assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } +TEST(chase_symlinks_at) { + _cleanup_(rm_rf_physical_and_freep) char *t = NULL; + _cleanup_close_ int tfd = -EBADF, fd = -EBADF; + _cleanup_free_ char *result = NULL; + const char *p; + + assert_se((tfd = mkdtemp_open(NULL, 0, &t)) >= 0); + + /* Test that AT_FDCWD with CHASE_AT_RESOLVE_IN_ROOT resolves against / and not the current working + * directory. */ + + assert_se(symlinkat("/usr", tfd, "abc") >= 0); + + p = strjoina(t, "/abc"); + assert_se(chase_symlinks_at(AT_FDCWD, p, CHASE_AT_RESOLVE_IN_ROOT, &result, NULL) >= 0); + assert_se(streq(result, "/usr")); + result = mfree(result); + + /* Test that absolute path or not are the same when resolving relative to a directory file + * descriptor and that we always get a relative path back. */ + + assert_se(fd = openat(tfd, "def", O_CREAT|O_CLOEXEC, 0700) >= 0); + fd = safe_close(fd); + assert_se(symlinkat("/def", tfd, "qed") >= 0); + assert_se(chase_symlinks_at(tfd, "qed", CHASE_AT_RESOLVE_IN_ROOT, &result, NULL) >= 0); + assert_se(streq(result, "def")); + result = mfree(result); + assert_se(chase_symlinks_at(tfd, "/qed", CHASE_AT_RESOLVE_IN_ROOT, &result, NULL) >= 0); + assert_se(streq(result, "def")); + result = mfree(result); + + /* Valid directory file descriptor without CHASE_AT_RESOLVE_IN_ROOT should resolve symlinks against + * host's root. */ + assert_se(chase_symlinks_at(tfd, "/qed", 0, &result, NULL) == -ENOENT); +} + TEST(unlink_noerrno) { char *name; int fd; |