diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-03-13 16:17:21 +0100 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-03-15 12:38:11 +0100 |
commit | 47f0e1b5e04c27572b540ae4a86e522d268ffd3c (patch) | |
tree | b01e0e1f57c7646a619087e3d74217d6215bec8b /src/test/test-fs-util.c | |
parent | chase-symlinks: Remove unused ret_fd arguments (diff) | |
download | systemd-47f0e1b5e04c27572b540ae4a86e522d268ffd3c.tar.xz systemd-47f0e1b5e04c27572b540ae4a86e522d268ffd3c.zip |
chase-symlinks: Rework open() functions and some chase flags
Currently, when CHASE_PARENT is specified, we chase the parent directory
of the symlink itself. Let's change this and chase the parent directory
of the symlink target so that trying to open the actual file later with
O_NOFOLLOW doesn't fail with ELOOP.
To get the current behavior, callers can add CHASE_NOFOLLOW to chase
the parent directory of the symlink itself.
Currently, when CHASE_MKDIR_0755 is specified, we create all components
of the path as directories. Instead, let's change the flag to only create
parent directories and leave the final component of the PATH untouched.
Also, allow CHASE_NONEXISTENT with CHASE_MKDIR_0755 now that it doesn't
create all components anymore.
Finally, rework chase_symlinks_and_open() and chase_symlinkat_at_and_open()
to always chase the parent directory and use xopenat() to open the final
component of the path. This allows us to pass O_CREAT to create the file or
directory (O_DIRECTORY) if it is missing. If CHASE_PARENT is configured, we
just reopen the parent directory that we chased.
Diffstat (limited to 'src/test/test-fs-util.c')
-rw-r--r-- | src/test/test-fs-util.c | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 065ad3c6e7..a18dc00fc5 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -331,10 +331,10 @@ TEST(chase_symlinks) { } assert_se(lstat(p, &st) >= 0); - r = chase_symlinks_and_unlink(p, NULL, 0, 0, &result); + r = chase_symlinks_and_unlink(p, NULL, 0, 0, &result); + assert_se(r == 0); assert_se(path_equal(result, p)); result = mfree(result); - assert_se(r == 0); assert_se(lstat(p, &st) == -1 && errno == ENOENT); /* Test CHASE_NOFOLLOW */ @@ -426,18 +426,6 @@ TEST(chase_symlinks) { assert_se(chase_symlinks("top/dot/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, NULL, NULL) == -EREMCHG); assert_se(chase_symlinks("top/dot/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_WARN, NULL, NULL) == -EREMCHG); - /* Test CHASE_PARENT */ - - assert_se(chase_symlinks("/chase/parent", temp, CHASE_PREFIX_ROOT|CHASE_PARENT|CHASE_NONEXISTENT, &result, NULL) >= 0); - p = strjoina(temp, "/chase"); - assert_se(streq(p, result)); - result = mfree(result); - assert_se(chase_symlinks("/chase", temp, CHASE_PREFIX_ROOT|CHASE_PARENT|CHASE_NONEXISTENT, &result, NULL) >= 0); - assert_se(streq(temp, result)); - result = mfree(result); - assert_se(chase_symlinks("/", temp, CHASE_PREFIX_ROOT|CHASE_PARENT|CHASE_NONEXISTENT, NULL, NULL) == -EADDRNOTAVAIL); - assert_se(chase_symlinks(".", temp, CHASE_PREFIX_ROOT|CHASE_PARENT|CHASE_NONEXISTENT, NULL, NULL) == -EADDRNOTAVAIL); - cleanup: assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } @@ -479,23 +467,51 @@ TEST(chase_symlinks_at) { /* Test CHASE_PARENT */ - assert_se(chase_symlinks_at(tfd, "chase/parent", CHASE_NONEXISTENT|CHASE_PARENT, &result, NULL) >= 0); + assert_se((fd = open_mkdir_at(tfd, "chase", O_CLOEXEC, 0755)) >= 0); + assert_se(symlinkat("/def", fd, "parent") >= 0); + fd = safe_close(fd); + + /* Make sure that when we chase a symlink parent directory, that we chase the parent directory of the + * symlink target and not the symlink itself. But if we add CHASE_NOFOLLOW, we get the parent + * directory of the symlink itself. */ + + assert_se(chase_symlinks_at(tfd, "chase/parent", CHASE_PARENT|CHASE_AT_RESOLVE_IN_ROOT, &result, &fd) >= 0); + assert_se(faccessat(fd, "def", F_OK, 0) >= 0); + assert_se(streq(result, "def")); + fd = safe_close(fd); + result = mfree(result); + + assert_se(chase_symlinks_at(tfd, "chase/parent", CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT|CHASE_NOFOLLOW, &result, &fd) >= 0); + assert_se(faccessat(fd, "parent", F_OK, AT_SYMLINK_NOFOLLOW) >= 0); + assert_se(streq(result, "chase/parent")); + fd = safe_close(fd); + result = mfree(result); + + assert_se(chase_symlinks_at(tfd, "chase", CHASE_PARENT|CHASE_AT_RESOLVE_IN_ROOT, &result, &fd) >= 0); + assert_se(faccessat(fd, "chase", F_OK, 0) >= 0); assert_se(streq(result, "chase")); + fd = safe_close(fd); result = mfree(result); - assert_se(chase_symlinks_at(tfd, "chase", CHASE_NONEXISTENT|CHASE_PARENT, &result, NULL) >= 0); + assert_se(chase_symlinks_at(tfd, "/", CHASE_PARENT|CHASE_AT_RESOLVE_IN_ROOT, &result, NULL) >= 0); + assert_se(streq(result, ".")); + result = mfree(result); + + assert_se(chase_symlinks_at(tfd, ".", CHASE_PARENT|CHASE_AT_RESOLVE_IN_ROOT, &result, NULL) >= 0); assert_se(streq(result, ".")); result = mfree(result); /* Test CHASE_MKDIR_0755 */ - assert_se(chase_symlinks_at(tfd, "m/k/d/i/r", CHASE_MKDIR_0755, &result, NULL) >= 0); - assert_se(faccessat(tfd, "m/k/d/i/r", F_OK, 0) >= 0); + assert_se(chase_symlinks_at(tfd, "m/k/d/i/r", CHASE_MKDIR_0755|CHASE_NONEXISTENT, &result, NULL) >= 0); + assert_se(faccessat(tfd, "m/k/d/i", F_OK, 0) >= 0); + assert_se(RET_NERRNO(faccessat(tfd, "m/k/d/i/r", F_OK, 0)) == -ENOENT); assert_se(streq(result, "m/k/d/i/r")); result = mfree(result); - assert_se(chase_symlinks_at(tfd, "m/../q", CHASE_MKDIR_0755, &result, NULL) >= 0); - assert_se(faccessat(tfd, "q", F_OK, 0) >= 0); + assert_se(chase_symlinks_at(tfd, "m/../q", CHASE_MKDIR_0755|CHASE_NONEXISTENT, &result, NULL) >= 0); + assert_se(faccessat(tfd, "m", F_OK, 0) >= 0); + assert_se(RET_NERRNO(faccessat(tfd, "q", F_OK, 0)) == -ENOENT); assert_se(streq(result, "q")); result = mfree(result); @@ -503,8 +519,14 @@ TEST(chase_symlinks_at) { /* Test chase_symlinks_at_and_open() */ - fd = chase_symlinks_at_and_open(tfd, "o/p/e/n", CHASE_MKDIR_0755, O_CLOEXEC, NULL); + fd = chase_symlinks_at_and_open(tfd, "o/p/e/n/f/i/l/e", CHASE_MKDIR_0755, O_CREAT|O_EXCL|O_CLOEXEC, NULL); + assert_se(fd >= 0); + assert_se(fd_verify_regular(fd) >= 0); + fd = safe_close(fd); + + fd = chase_symlinks_at_and_open(tfd, "o/p/e/n/d/i/r", CHASE_MKDIR_0755, O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, NULL); assert_se(fd >= 0); + assert_se(fd_verify_directory(fd) >= 0); fd = safe_close(fd); } |