diff --git a/mkosi/mkosi.sanitizers/mkosi.postinst b/mkosi/mkosi.sanitizers/mkosi.postinst index 9806f7aab3..04c019cf2c 100755 --- a/mkosi/mkosi.sanitizers/mkosi.postinst +++ b/mkosi/mkosi.sanitizers/mkosi.postinst @@ -62,6 +62,7 @@ wrap=( findmnt getent getfacl + groups id integritysetup iscsid diff --git a/src/basic/chase.c b/src/basic/chase.c index 9219209421..ddef194487 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -21,6 +21,7 @@ #define CHASE_NO_SHORTCUT_MASK \ (CHASE_NONEXISTENT | \ CHASE_NO_AUTOFS | \ + CHASE_TRIGGER_AUTOFS | \ CHASE_SAFE | \ CHASE_STEP | \ CHASE_PROHIBIT_SYMLINKS | \ @@ -92,7 +93,7 @@ static int openat_opath_with_automount(int dir_fd, const char *path, bool automo /* Pin an inode via O_PATH semantics. Sounds pretty obvious to do this, right? You just do open() * with O_PATH, and there you go. But uh, it's not that easy. open() via O_PATH does not trigger - * automounts, but we usually want that (except if CHASE_NO_AUTOFS is used). But thankfully there's + * automounts, but we may want that when CHASE_TRIGGER_AUTOFS is set. But thankfully there's * a way out: the newer open_tree() call, when specified without OPEN_TREE_CLONE actually is fully * equivalent to open() with O_PATH – except for one thing: it triggers automounts. * @@ -133,6 +134,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int assert(!FLAGS_SET(flags, CHASE_PREFIX_ROOT)); assert(!FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY|CHASE_MUST_BE_REGULAR)); assert(!FLAGS_SET(flags, CHASE_STEP|CHASE_EXTRACT_FILENAME)); + assert(!FLAGS_SET(flags, CHASE_NO_AUTOFS|CHASE_TRIGGER_AUTOFS)); assert(dir_fd >= 0 || dir_fd == AT_FDCWD); if (FLAGS_SET(flags, CHASE_STEP)) @@ -401,7 +403,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int } /* Otherwise let's pin it by file descriptor, via O_PATH. */ - child = r = openat_opath_with_automount(fd, first, /* automount = */ !FLAGS_SET(flags, CHASE_NO_AUTOFS)); + child = r = openat_opath_with_automount(fd, first, /* automount = */ FLAGS_SET(flags, CHASE_TRIGGER_AUTOFS)); if (r < 0) { if (r != -ENOENT) return r; diff --git a/src/basic/chase.h b/src/basic/chase.h index 36632c8a32..554ab6cadd 100644 --- a/src/basic/chase.h +++ b/src/basic/chase.h @@ -7,27 +7,28 @@ typedef enum ChaseFlags { CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */ CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */ CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */ - CHASE_SAFE = 1 << 3, /* Return -EPERM if we ever traverse from unprivileged to privileged files or directories */ - CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */ - CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */ - CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most component. With ret_fd, when the path's + CHASE_TRIGGER_AUTOFS = 1 << 3, /* Use open_tree() rather than openat() to trigger autofs mount */ + CHASE_SAFE = 1 << 4, /* Return -EPERM if we ever traverse from unprivileged to privileged files or directories */ + CHASE_TRAIL_SLASH = 1 << 5, /* Any trailing slash will be preserved */ + CHASE_STEP = 1 << 6, /* Just execute a single step of the normalization */ + CHASE_NOFOLLOW = 1 << 7, /* Do not follow the path's right-most component. With ret_fd, when the path's * right-most component refers to symlink, return O_PATH fd of the symlink. */ - CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered. + CHASE_WARN = 1 << 8, /* Emit an appropriate warning when an error is encountered. * Note: this may do an NSS lookup, hence this flag cannot be used in PID 1. */ - CHASE_AT_RESOLVE_IN_ROOT = 1 << 8, /* Same as openat2()'s RESOLVE_IN_ROOT flag, symlinks are resolved + CHASE_AT_RESOLVE_IN_ROOT = 1 << 9, /* Same as openat2()'s RESOLVE_IN_ROOT flag, symlinks are resolved * relative to the given directory fd instead of root. */ - CHASE_PROHIBIT_SYMLINKS = 1 << 9, /* Refuse all symlinks */ - CHASE_PARENT = 1 << 10, /* Chase the parent directory of the given path. Note that the + CHASE_PROHIBIT_SYMLINKS = 1 << 10, /* Refuse all symlinks */ + CHASE_PARENT = 1 << 11, /* Chase the parent directory of the given path. Note that the * full path is still stored in ret_path and only the returned * file descriptor will point to the parent directory. Note that * the result path is the root or '.', then the file descriptor * also points to the result path even if this flag is set. * When this specified, chase() will succeed with 1 even if the * file points to the last path component does not exist. */ - CHASE_MKDIR_0755 = 1 << 11, /* Create any missing directories in the given path. */ - CHASE_EXTRACT_FILENAME = 1 << 12, /* Only return the last component of the resolved path */ - CHASE_MUST_BE_DIRECTORY = 1 << 13, /* Fail if returned inode fd is not a dir */ - CHASE_MUST_BE_REGULAR = 1 << 14, /* Fail if returned inode fd is not a regular file */ + CHASE_MKDIR_0755 = 1 << 12, /* Create any missing directories in the given path. */ + CHASE_EXTRACT_FILENAME = 1 << 13, /* Only return the last component of the resolved path */ + CHASE_MUST_BE_DIRECTORY = 1 << 14, /* Fail if returned inode fd is not a dir */ + CHASE_MUST_BE_REGULAR = 1 << 15, /* Fail if returned inode fd is not a regular file */ } ChaseFlags; bool unsafe_transition(const struct stat *a, const struct stat *b); diff --git a/src/bootctl/bootctl-install.c b/src/bootctl/bootctl-install.c index ddeed5ecf1..27ec4cf0fe 100644 --- a/src/bootctl/bootctl-install.c +++ b/src/bootctl/bootctl-install.c @@ -343,7 +343,7 @@ static int update_efi_boot_binaries(const char *esp_path, const char *source_pat assert(esp_path); assert(source_path); - r = chase_and_opendir("/EFI/BOOT", esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &p, &d); + r = chase_and_opendir("/EFI/BOOT", esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, &p, &d); if (r == -ENOENT) return 0; if (r < 0) @@ -396,10 +396,10 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) { if (!p) return log_oom(); - r = chase(p, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &source_path, NULL); + r = chase(p, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, &source_path, NULL); /* If we had a root directory to try, we didn't find it and we are in auto mode, retry on the host */ if (r == -ENOENT && root && arg_install_source == ARG_INSTALL_SOURCE_AUTO) - r = chase(p, NULL, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &source_path, NULL); + r = chase(p, NULL, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, &source_path, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve path %s%s%s: %m", @@ -411,7 +411,7 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) { if (!q) return log_oom(); - r = chase(q, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_NONEXISTENT, &dest_path, NULL); + r = chase(q, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_NONEXISTENT|CHASE_TRIGGER_AUTOFS, &dest_path, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", q, esp_path); @@ -428,7 +428,7 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) { v = strjoina("/EFI/BOOT/BOOT", e); ascii_strupper(strrchr(v, '/') + 1); - r = chase(v, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_NONEXISTENT, &default_dest_path, NULL); + r = chase(v, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_NONEXISTENT|CHASE_TRIGGER_AUTOFS, &default_dest_path, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", v, esp_path); @@ -449,10 +449,10 @@ static int install_binaries(const char *esp_path, const char *arch, bool force) _cleanup_free_ char *path = NULL; int r; - r = chase_and_opendir(BOOTLIBDIR, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &path, &d); + r = chase_and_opendir(BOOTLIBDIR, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, &path, &d); /* If we had a root directory to try, we didn't find it and we are in auto mode, retry on the host */ if (r == -ENOENT && root && arg_install_source == ARG_INSTALL_SOURCE_AUTO) - r = chase_and_opendir(BOOTLIBDIR, NULL, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &path, &d); + r = chase_and_opendir(BOOTLIBDIR, NULL, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, &path, &d); if (r == -ENOENT && arg_graceful) { log_debug("Source directory does not exist, ignoring."); return 0; @@ -634,7 +634,7 @@ static int install_secure_boot_auto_enroll(const char *esp, X509 *certificate, E if (r < 0) return r; - _cleanup_close_ int keys_fd = chase_and_open("loader/keys/auto", esp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, O_DIRECTORY, NULL); + _cleanup_close_ int keys_fd = chase_and_open("loader/keys/auto", esp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, O_DIRECTORY, NULL); if (keys_fd < 0) return log_error_errno(keys_fd, "Failed to chase loader/keys/auto in the ESP: %m"); @@ -881,7 +881,7 @@ static int install_variables( uint16_t slot; int r; - r = chase_and_access(path, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, F_OK, NULL); + r = chase_and_access(path, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, F_OK, NULL); if (r == -ENOENT) return 0; if (r < 0) @@ -1097,7 +1097,7 @@ static int remove_boot_efi(const char *esp_path) { _cleanup_free_ char *p = NULL; int r, c = 0; - r = chase_and_opendir("/EFI/BOOT", esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &p, &d); + r = chase_and_opendir("/EFI/BOOT", esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, &p, &d); if (r == -ENOENT) return 0; if (r < 0) diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c index 2c3208a471..81fdeed64e 100644 --- a/src/bootctl/bootctl-status.c +++ b/src/bootctl/bootctl-status.c @@ -222,7 +222,7 @@ static int enumerate_binaries( assert(previous); assert(is_first); - r = chase_and_opendir(path, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &p, &d); + r = chase_and_opendir(path, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, &p, &d); if (r == -ENOENT) return 0; if (r < 0) @@ -693,7 +693,7 @@ static void deref_unlink_file(Hashmap **known_files, const char *fn, const char return; if (arg_dry_run) { - r = chase_and_access(fn, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, F_OK, &path); + r = chase_and_access(fn, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, F_OK, &path); if (r < 0) log_info_errno(r, "Unable to determine whether \"%s\" exists, ignoring: %m", fn); else @@ -701,7 +701,7 @@ static void deref_unlink_file(Hashmap **known_files, const char *fn, const char return; } - r = chase_and_unlink(fn, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, 0, &path); + r = chase_and_unlink(fn, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, 0, &path); if (r >= 0) log_info("Removed \"%s\"", path); else if (r != -ENOENT) @@ -709,7 +709,7 @@ static void deref_unlink_file(Hashmap **known_files, const char *fn, const char _cleanup_free_ char *d = NULL; if (path_extract_directory(fn, &d) >= 0 && !path_equal(d, "/")) { - r = chase_and_unlink(d, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, AT_REMOVEDIR, NULL); + r = chase_and_unlink(d, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, AT_REMOVEDIR, NULL); if (r < 0 && !IN_SET(r, -ENOTEMPTY, -ENOENT)) log_warning_errno(r, "Failed to remove directory \"%s\", ignoring: %m", d); } @@ -801,7 +801,7 @@ static int unlink_entry(const BootConfig *config, const char *root, const char * if (arg_dry_run) log_info("Would remove \"%s\"", e->path); else { - r = chase_and_unlink(e->path, root, CHASE_PROHIBIT_SYMLINKS, 0, NULL); + r = chase_and_unlink(e->path, root, CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, 0, NULL); if (r < 0) return log_error_errno(r, "Failed to remove \"%s\": %m", e->path); @@ -862,7 +862,7 @@ static int cleanup_orphaned_files( if (r < 0) return log_error_errno(r, "Failed to count files in %s: %m", root); - dir_fd = chase_and_open(arg_entry_token, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, + dir_fd = chase_and_open(arg_entry_token, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, O_DIRECTORY|O_CLOEXEC, &full); if (dir_fd == -ENOENT) return 0; diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 1e2945eb91..72050aad69 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -3985,7 +3985,7 @@ static int apply_working_directory( r = chase(wd, runtime->ephemeral_copy ?: context->root_directory, - CHASE_PREFIX_ROOT|CHASE_AT_RESOLVE_IN_ROOT, + CHASE_PREFIX_ROOT|CHASE_AT_RESOLVE_IN_ROOT|CHASE_TRIGGER_AUTOFS, /* ret_path= */ NULL, &dfd); if (r >= 0) diff --git a/src/core/mount.c b/src/core/mount.c index e1e6cf2b2f..36a877ab14 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1196,7 +1196,7 @@ static void mount_enter_mounting(Mount *m) { /* Validate that the path we are overmounting does not contain any symlinks, because if it does, we * couldn't support that reasonably: the mounts in /proc/self/mountinfo would not be recognizable to * us anymore. */ - fd = chase_and_open_parent(m->where, /* root= */ NULL, CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755, &fn); + fd = chase_and_open_parent(m->where, /* root= */ NULL, CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_TRIGGER_AUTOFS, &fn); if (fd == -EREMCHG) { r = unit_log_noncanonical_mount_path(UNIT(m), m->where); goto fail; diff --git a/src/core/namespace.c b/src/core/namespace.c index 644614a184..283a1108ce 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1793,7 +1793,7 @@ static int follow_symlink( * a time by specifying CHASE_STEP. This function returns 0 if we resolved one step, and > 0 if we reached the * end and already have a fully normalized name. */ - r = chase(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target, NULL); + r = chase(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT|CHASE_TRIGGER_AUTOFS, &target, NULL); if (r < 0) return log_debug_errno(r, "Failed to chase symlinks '%s': %m", mount_entry_path(m)); if (r > 0) /* Reached the end, nothing more to resolve */ @@ -1991,7 +1991,7 @@ static int apply_one_mount( return log_error_errno(r, "Failed to set label of the source directory %s: %m", mount_entry_source(m)); } - r = chase(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased, NULL); + r = chase(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH|CHASE_TRIGGER_AUTOFS, &chased, NULL); if (r == -ENOENT && m->ignore) { log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m)); return 0; @@ -3434,7 +3434,7 @@ static int is_extension_overlay(const char *path, int fd) { assert(path); if (fd < 0) { - r = chase(path, /* root= */ NULL, CHASE_TRAIL_SLASH|CHASE_MUST_BE_DIRECTORY, /* ret_path= */ NULL, &dfd); + r = chase(path, /* root= */ NULL, CHASE_TRAIL_SLASH|CHASE_MUST_BE_DIRECTORY|CHASE_TRIGGER_AUTOFS, /* ret_path= */ NULL, &dfd); if (r < 0) return r; fd = dfd; diff --git a/src/core/service.c b/src/core/service.c index d94162ead0..c8cda06099 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -5622,7 +5622,7 @@ int service_determine_exec_selinux_label(Service *s, char **ret) { return -ENODATA; _cleanup_free_ char *path = NULL; - r = chase(c->path, s->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL); + r = chase(c->path, s->exec_context.root_directory, CHASE_PREFIX_ROOT|CHASE_TRIGGER_AUTOFS, &path, NULL); if (r < 0) { log_unit_debug_errno(UNIT(s), r, "Failed to resolve service binary '%s', ignoring.", c->path); return -ENODATA; diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index a684c0bef8..c8bb9a192b 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -91,7 +91,7 @@ static int parse_where(const char *input, char **ret_where) { assert(ret_where); if (arg_transport == BUS_TRANSPORT_LOCAL && arg_canonicalize) { - r = chase(input, /* root= */ NULL, CHASE_NONEXISTENT, ret_where, /* ret_fd= */ NULL); + r = chase(input, /* root= */ NULL, CHASE_NONEXISTENT|CHASE_TRIGGER_AUTOFS, ret_where, /* ret_fd= */ NULL); if (r < 0) return log_error_errno(r, "Failed to make path %s absolute: %m", input); } else { @@ -476,7 +476,7 @@ static int parse_argv(int argc, char *argv[]) { } if (arg_transport == BUS_TRANSPORT_LOCAL && arg_canonicalize) { - r = chase(p, /* root= */ NULL, /* flags= */ 0, &arg_mount_what, /* ret_fd= */ NULL); + r = chase(p, /* root= */ NULL, CHASE_TRIGGER_AUTOFS, &arg_mount_what, /* ret_fd= */ NULL); if (r < 0) return log_error_errno(r, "Failed to chase path '%s': %m", p); } else { @@ -1103,7 +1103,7 @@ static int action_umount(sd_bus *bus, int argc, char **argv) { return log_oom(); _cleanup_close_ int fd = -EBADF; - r = chase(u, /* root= */ NULL, 0, &p, &fd); + r = chase(u, /* root= */ NULL, CHASE_TRIGGER_AUTOFS, &p, &fd); if (r < 0) { RET_GATHER(ret, log_error_errno(r, "Failed to chase path '%s': %m", u)); continue; diff --git a/src/mountfsd/mountwork.c b/src/mountfsd/mountwork.c index 207609d232..bfb8c05c22 100644 --- a/src/mountfsd/mountwork.c +++ b/src/mountfsd/mountwork.c @@ -176,7 +176,7 @@ static int verify_trusted_image_fd_by_path(int fd) { struct stat stb; const char *e; - r = chase(s, NULL, CHASE_SAFE, &q, &dir_fd); + r = chase(s, NULL, CHASE_SAFE|CHASE_TRIGGER_AUTOFS, &q, &dir_fd); if (r == -ENOENT) continue; if (r < 0) { @@ -194,7 +194,7 @@ static int verify_trusted_image_fd_by_path(int fd) { if (!filename_is_valid(e)) continue; - r = chaseat(dir_fd, e, CHASE_SAFE, NULL, &inode_fd); + r = chaseat(dir_fd, e, CHASE_SAFE|CHASE_TRIGGER_AUTOFS, NULL, &inode_fd); if (r < 0) return log_error_errno(r, "Couldn't verify that specified image '%s' is in search path '%s': %m", p, s); diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c index eeec050b60..eabc3efc5e 100644 --- a/src/shared/find-esp.c +++ b/src/shared/find-esp.c @@ -371,7 +371,7 @@ static int verify_esp( /* Non-root user can only check the status, so if an error occurred in the following, it does not cause any * issues. Let's also, silence the error messages. */ - r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT, &p, &pfd); + r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT|CHASE_TRIGGER_AUTOFS, &p, &pfd); if (r < 0) return log_full_errno((searching && r == -ENOENT) || (unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR, @@ -492,7 +492,7 @@ int find_esp_and_warn_at( "$SYSTEMD_ESP_PATH does not refer to an absolute path, refusing to use it: %s", path); - r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT, &p, &fd); + r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_TRIGGER_AUTOFS, &p, &fd); if (r < 0) return log_error_errno(r, "Failed to resolve path %s: %m", path); @@ -766,7 +766,7 @@ static int verify_xbootldr( assert(rfd >= 0 || rfd == AT_FDCWD); assert(path); - r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT, &p, &pfd); + r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT|CHASE_TRIGGER_AUTOFS, &p, &pfd); if (r < 0) return log_full_errno((searching && r == -ENOENT) || (unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR, @@ -844,7 +844,7 @@ int find_xbootldr_and_warn_at( "$SYSTEMD_XBOOTLDR_PATH does not refer to an absolute path, refusing to use it: %s", path); - r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT, &p, &fd); + r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_TRIGGER_AUTOFS, &p, &fd); if (r < 0) return log_error_errno(r, "Failed to resolve path %s: %m", p); diff --git a/src/sysupdate/sysupdate-resource.c b/src/sysupdate/sysupdate-resource.c index 549edcf9d4..b0fa799fd1 100644 --- a/src/sysupdate/sysupdate-resource.c +++ b/src/sysupdate/sysupdate-resource.c @@ -660,7 +660,7 @@ int resource_resolve_path( _cleanup_free_ char *resolved = NULL; struct stat st; - r = chase(rr->path, root, CHASE_PREFIX_ROOT, &resolved, &fd); + r = chase(rr->path, root, CHASE_PREFIX_ROOT|CHASE_TRIGGER_AUTOFS, &resolved, &fd); if (r < 0) return log_error_errno(r, "Failed to resolve '%s': %m", rr->path); @@ -697,7 +697,7 @@ int resource_resolve_path( } else if (RESOURCE_IS_FILESYSTEM(rr->type)) { _cleanup_free_ char *resolved = NULL, *relative_to = NULL; - ChaseFlags chase_flags = CHASE_NONEXISTENT | CHASE_PREFIX_ROOT; + ChaseFlags chase_flags = CHASE_NONEXISTENT | CHASE_PREFIX_ROOT | CHASE_TRIGGER_AUTOFS; if (rr->path_relative_to == PATH_RELATIVE_TO_EXPLICIT) { assert(relative_to_directory); diff --git a/src/sysupdate/sysupdate-transfer.c b/src/sysupdate/sysupdate-transfer.c index 82fd931dab..cb57d4af09 100644 --- a/src/sysupdate/sysupdate-transfer.c +++ b/src/sysupdate/sysupdate-transfer.c @@ -1498,7 +1498,7 @@ int transfer_install_instance( assert_not_reached(); if (resolve_link_path && root) { - r = chase(link_path, root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved, NULL); + r = chase(link_path, root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT|CHASE_TRIGGER_AUTOFS, &resolved, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve current symlink path '%s': %m", link_path); diff --git a/src/test/test-chase-manual.c b/src/test/test-chase-manual.c index 03c0a245bd..376cd12c42 100644 --- a/src/test/test-chase-manual.c +++ b/src/test/test-chase-manual.c @@ -25,6 +25,7 @@ static int parse_argv(int argc, char *argv[]) { { "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT }, { "nonexistent", no_argument, NULL, CHASE_NONEXISTENT }, { "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS }, + { "trigger-autofs", no_argument, NULL, CHASE_TRIGGER_AUTOFS }, { "safe", no_argument, NULL, CHASE_SAFE }, { "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH }, { "step", no_argument, NULL, CHASE_STEP }, @@ -61,6 +62,7 @@ static int parse_argv(int argc, char *argv[]) { case CHASE_PREFIX_ROOT: case CHASE_NONEXISTENT: case CHASE_NO_AUTOFS: + case CHASE_TRIGGER_AUTOFS: case CHASE_SAFE: case CHASE_TRAIL_SLASH: case CHASE_STEP: diff --git a/test/units/TEST-74-AUX-UTILS.userdbctl.sh b/test/units/TEST-74-AUX-UTILS.userdbctl.sh index 5592777849..53edb962e7 100755 --- a/test/units/TEST-74-AUX-UTILS.userdbctl.sh +++ b/test/units/TEST-74-AUX-UTILS.userdbctl.sh @@ -46,3 +46,18 @@ userdbctl user 65534 -j | userdbctl -F- user | cmp - <(userdbctl user 65534) userdbctl group root -j | userdbctl -F- group | cmp - <(userdbctl group root) userdbctl group systemd-network -j | userdbctl -F- group | cmp - <(userdbctl group systemd-network) userdbctl group 65534 -j | userdbctl -F- group | cmp - <(userdbctl group 65534) + +# Ensure NSS doesn't try to automount via open_tree +if [[ ! -v ASAN_OPTIONS ]]; then + systemctl stop systemd-userdbd.socket systemd-userdbd.service + set +o pipefail + systemd-run -q -t --property SystemCallFilter=~open_tree id definitelynotarealuser | grep -q "no such user" + systemd-run -q -t --property SystemCallFilter=~open_tree id --groups definitelynotarealuser | grep -q "no such user" + systemd-run -q -t --property SystemCallFilter=~open_tree groups definitelynotarealuser | grep -q "no such user" + set -o pipefail + # getent shows no output when the entry is not found, but exists with 2, while sd-run crashing will exit + # with 1 + assert_rc 2 systemd-run -q -t --property SystemCallFilter=~open_tree getent passwd definitelynotarealuser + assert_rc 2 systemd-run -q -t --property SystemCallFilter=~open_tree getent group definitelynotarealgroup + systemctl start systemd-userdbd.socket systemd-userdbd.service +fi