From be1117f712904b6a16b05db946d71e09ee3a5519 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2025 14:12:37 +0200 Subject: [PATCH 1/3] chase: mask away CHASE_MUST_BE_REGULAR in chase_openat() We pin the parent directory of the specified directory via CHASE_PARENT, but if we do that we really should mask off CHASE_MUST_BE_REGULAR, because a parent dir of course is a dir, nothing else. The CHASE_MUST_BE_REGULAR after all should apply to the file created in that dir, not to the parent. --- src/basic/chase.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index ddef194487..af9bc7b823 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -796,7 +796,7 @@ int chase_and_open( /* xopen_flags = */ 0, MODE_INVALID); - r = chase(path, root, CHASE_PARENT|chase_flags, &p, &path_fd); + r = chase(path, root, (CHASE_PARENT|chase_flags)&~CHASE_MUST_BE_REGULAR, &p, &path_fd); if (r < 0) return r; assert(path_fd >= 0); @@ -1001,7 +1001,7 @@ int chase_and_openat( /* xopen_flags = */ 0, MODE_INVALID); - r = chaseat(dir_fd, path, chase_flags|CHASE_PARENT, &p, &path_fd); + r = chaseat(dir_fd, path, (chase_flags|CHASE_PARENT)&~CHASE_MUST_BE_REGULAR, &p, &path_fd); if (r < 0) return r; From fb7151a3506e56af15ca400cf8463a1e397f753d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2025 14:15:48 +0200 Subject: [PATCH 2/3] chase: honour CHASE_MUST_BE_DIRECTORY/CHASE_MUST_BE_REGULAR properly in chase_and_openat() and related calls --- src/basic/chase.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index af9bc7b823..a1b0752601 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -789,11 +789,17 @@ int chase_and_open( assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); + XOpenFlags xopen_flags = 0; + if (FLAGS_SET(chase_flags, CHASE_MUST_BE_DIRECTORY)) + open_flags |= O_DIRECTORY; + if (FLAGS_SET(chase_flags, CHASE_MUST_BE_REGULAR)) + xopen_flags |= XO_REGULAR; + if (empty_or_root(root) && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) /* Shortcut this call if none of the special features of this call are requested */ return xopenat_full(AT_FDCWD, path, open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0), - /* xopen_flags = */ 0, + xopen_flags, MODE_INVALID); r = chase(path, root, (CHASE_PARENT|chase_flags)&~CHASE_MUST_BE_REGULAR, &p, &path_fd); @@ -808,7 +814,7 @@ int chase_and_open( return r; } - r = xopenat_full(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, MODE_INVALID); + r = xopenat_full(path_fd, strempty(fname), open_flags|O_NOFOLLOW, xopen_flags, MODE_INVALID); if (r < 0) return r; @@ -824,7 +830,7 @@ int chase_and_opendir(const char *path, const char *root, ChaseFlags chase_flags DIR *d; int r; - assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); + assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR))); assert(ret_dir); if (empty_or_root(root) && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) { @@ -837,7 +843,7 @@ int chase_and_opendir(const char *path, const char *root, ChaseFlags chase_flags return 0; } - r = chase(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + r = chase(path, root, chase_flags|CHASE_MUST_BE_DIRECTORY, ret_path ? &p : NULL, &path_fd); if (r < 0) return r; assert(path_fd >= 0); @@ -922,7 +928,7 @@ int chase_and_fopen_unlocked( int mode_flags, r; assert(path); - assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_PARENT))); + assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_PARENT|CHASE_MUST_BE_DIRECTORY))); assert(open_flags); assert(ret_file); @@ -994,11 +1000,17 @@ int chase_and_openat( assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); + XOpenFlags xopen_flags = 0; + if (FLAGS_SET(chase_flags, CHASE_MUST_BE_DIRECTORY)) + open_flags |= O_DIRECTORY; + if (FLAGS_SET(chase_flags, CHASE_MUST_BE_REGULAR)) + xopen_flags |= XO_REGULAR; + if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) /* Shortcut this call if none of the special features of this call are requested */ return xopenat_full(dir_fd, path, open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0), - /* xopen_flags = */ 0, + xopen_flags, MODE_INVALID); r = chaseat(dir_fd, path, (chase_flags|CHASE_PARENT)&~CHASE_MUST_BE_REGULAR, &p, &path_fd); @@ -1011,7 +1023,12 @@ int chase_and_openat( return r; } - r = xopenat_full(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags= */ 0, MODE_INVALID); + r = xopenat_full( + path_fd, + strempty(fname), + open_flags|O_NOFOLLOW, + xopen_flags, + MODE_INVALID); if (r < 0) return r; @@ -1027,7 +1044,7 @@ int chase_and_opendirat(int dir_fd, const char *path, ChaseFlags chase_flags, ch DIR *d; int r; - assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); + assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR))); assert(ret_dir); if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) { From 96deac2bf142faac6cd496bd76b8d39d3af17d59 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Sep 2025 18:43:31 +0200 Subject: [PATCH 3/3] sd-id128: tighten rules on chasing machine-id files --- src/libsystemd/sd-id128/sd-id128.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index d3838ba245..e08f0b6412 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -136,7 +136,6 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { } int id128_get_machine_at(int rfd, sd_id128_t *ret) { - _cleanup_close_ int fd = -EBADF; int r; assert(rfd >= 0 || rfd == AT_FDCWD); @@ -147,7 +146,8 @@ int id128_get_machine_at(int rfd, sd_id128_t *ret) { if (r > 0) return sd_id128_get_machine(ret); - fd = chase_and_openat(rfd, "/etc/machine-id", CHASE_AT_RESOLVE_IN_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL); + _cleanup_close_ int fd = + chase_and_openat(rfd, "/etc/machine-id", CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_REGULAR, O_RDONLY|O_CLOEXEC|O_NOCTTY, /* ret_path= */ NULL); if (fd < 0) return fd; @@ -155,12 +155,11 @@ int id128_get_machine_at(int rfd, sd_id128_t *ret) { } int id128_get_machine(const char *root, sd_id128_t *ret) { - _cleanup_close_ int fd = -EBADF; - if (empty_or_root(root)) return sd_id128_get_machine(ret); - fd = chase_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL); + _cleanup_close_ int fd = + chase_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT|CHASE_MUST_BE_REGULAR, O_RDONLY|O_CLOEXEC|O_NOCTTY, /* ret_path= */ NULL); if (fd < 0) return fd;