diff --git a/src/basic/chase.c b/src/basic/chase.c index a78645f24c..ddef194487 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -18,6 +18,16 @@ #include "strv.h" #include "user-util.h" +#define CHASE_NO_SHORTCUT_MASK \ + (CHASE_NONEXISTENT | \ + CHASE_NO_AUTOFS | \ + CHASE_TRIGGER_AUTOFS | \ + CHASE_SAFE | \ + CHASE_STEP | \ + CHASE_PROHIBIT_SYMLINKS | \ + CHASE_PARENT | \ + CHASE_MKDIR_0755) + bool unsafe_transition(const struct stat *a, const struct stat *b) { /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files @@ -83,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 (when CHASE_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. * @@ -124,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)) @@ -202,7 +213,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int * -ENOLINK. If CHASE_WARN is also set, a warning describing the unsafe transition is emitted. * CHASE_WARN cannot be used in PID 1. * - * 5. Without CHASE_AUTOFS: in this case if an autofs mount point is encountered, path normalization + * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization * is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of * the mount point is emitted. CHASE_WARN cannot be used in PID 1. */ @@ -218,11 +229,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int flags &= ~CHASE_AT_RESOLVE_IN_ROOT; } - if (!(flags & - (CHASE_AT_RESOLVE_IN_ROOT|CHASE_NONEXISTENT|CHASE_AUTOFS|CHASE_SAFE|CHASE_STEP| - CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_PARENT)) && - !ret_path && ret_fd) { - + if (!ret_path && ret_fd && (flags & (CHASE_AT_RESOLVE_IN_ROOT|CHASE_NO_SHORTCUT_MASK)) == 0) { /* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root * set and doesn't care about any of the other special features we provide either. */ r = openat(dir_fd, path, O_PATH|O_CLOEXEC|(FLAGS_SET(flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); @@ -396,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_AUTOFS)); + child = r = openat_opath_with_automount(fd, first, /* automount = */ FLAGS_SET(flags, CHASE_TRIGGER_AUTOFS)); if (r < 0) { if (r != -ENOENT) return r; @@ -435,7 +442,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int unsafe_transition(&st, &st_child)) return log_unsafe_transition(fd, child, path, flags); - if (!FLAGS_SET(flags, CHASE_AUTOFS) && + if (FLAGS_SET(flags, CHASE_NO_AUTOFS) && fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0) return log_autofs_mount_point(child, path, flags); @@ -782,8 +789,7 @@ int chase_and_open( assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); - if (empty_or_root(root) && !ret_path && - (chase_flags & (CHASE_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) + 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), @@ -821,8 +827,7 @@ int chase_and_opendir(const char *path, const char *root, ChaseFlags chase_flags assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); assert(ret_dir); - if (empty_or_root(root) && !ret_path && - (chase_flags & (CHASE_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) { + 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 */ d = opendir(path); if (!d) @@ -857,8 +862,7 @@ int chase_and_stat(const char *path, const char *root, ChaseFlags chase_flags, c assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); assert(ret_stat); - if (empty_or_root(root) && !ret_path && - (chase_flags & (CHASE_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) + 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 RET_NERRNO(fstatat(AT_FDCWD, path, ret_stat, FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0)); @@ -885,8 +889,7 @@ int chase_and_access(const char *path, const char *root, ChaseFlags chase_flags, assert(path); assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); - if (empty_or_root(root) && !ret_path && - (chase_flags & (CHASE_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) + 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 RET_NERRNO(faccessat(AT_FDCWD, path, access_mode, FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0)); @@ -991,8 +994,7 @@ int chase_and_openat( assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); - if (dir_fd == AT_FDCWD && !ret_path && - (chase_flags & (CHASE_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) + 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), @@ -1028,8 +1030,7 @@ int chase_and_opendirat(int dir_fd, const char *path, ChaseFlags chase_flags, ch assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); assert(ret_dir); - if (dir_fd == AT_FDCWD && !ret_path && - (chase_flags & (CHASE_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) { + 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 */ d = opendir(path); if (!d) @@ -1064,8 +1065,7 @@ int chase_and_statat(int dir_fd, const char *path, ChaseFlags chase_flags, char assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); assert(ret_stat); - if (dir_fd == AT_FDCWD && !ret_path && - (chase_flags & (CHASE_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) + 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 RET_NERRNO(fstatat(AT_FDCWD, path, ret_stat, FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0)); @@ -1092,8 +1092,7 @@ int chase_and_accessat(int dir_fd, const char *path, ChaseFlags chase_flags, int assert(path); assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))); - if (dir_fd == AT_FDCWD && !ret_path && - (chase_flags & (CHASE_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) + 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 RET_NERRNO(faccessat(AT_FDCWD, path, access_mode, FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0)); diff --git a/src/basic/chase.h b/src/basic/chase.h index 87c551a3bd..554ab6cadd 100644 --- a/src/basic/chase.h +++ b/src/basic/chase.h @@ -6,28 +6,29 @@ 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_AUTOFS = 1 << 2, /* Trigger automount if autofs mount point found instead of returning -EREMOTE */ - 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_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */ + 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 2bbf7fea99..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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, 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|CHASE_AUTOFS, 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|CHASE_AUTOFS, &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 eaaba41c95..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|CHASE_AUTOFS, &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|CHASE_AUTOFS, 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|CHASE_AUTOFS, 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|CHASE_AUTOFS, 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|CHASE_AUTOFS, 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|CHASE_AUTOFS, + 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 fda67c8fd9..72050aad69 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -3079,7 +3079,7 @@ static int setup_exec_directory( * since they all support the private/ symlink logic at least in some * configurations, see above. */ - r = chase(target, NULL, CHASE_AUTOFS, &target_resolved, NULL); + r = chase(target, NULL, 0, &target_resolved, NULL); if (r < 0) goto fail; @@ -3090,7 +3090,7 @@ static int setup_exec_directory( } /* /var/lib or friends may be symlinks. So, let's chase them also. */ - r = chase(q, NULL, CHASE_NONEXISTENT|CHASE_AUTOFS, &q_resolved, NULL); + r = chase(q, NULL, CHASE_NONEXISTENT, &q_resolved, NULL); if (r < 0) goto fail; @@ -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_AUTOFS, + 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 85bcc6fdf9..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|CHASE_AUTOFS, &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 21335e66df..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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, /* 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 06d8a67356..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|CHASE_AUTOFS, &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/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 13bf7beab5..0951e13e87 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -2476,7 +2476,7 @@ int device_chase(sd_device *device, const char *path, ChaseFlags flags, char **r _cleanup_free_ char *resolved = NULL; _cleanup_close_ int fd = -EBADF; - r = chase(path, /* root = */ NULL, flags, &resolved, ret_fd ? &fd : NULL); + r = chase(path, /* root = */ NULL, CHASE_NO_AUTOFS | flags, &resolved, ret_fd ? &fd : NULL); if (r < 0) return r; diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index e089c40231..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|CHASE_AUTOFS, 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, CHASE_AUTOFS, &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, CHASE_AUTOFS, &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 caeadb37b1..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|CHASE_AUTOFS, &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|CHASE_AUTOFS, 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 2d58980ccd..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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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|CHASE_AUTOFS, &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 b97a467f02..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|CHASE_AUTOFS, &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 | CHASE_AUTOFS; + 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 9773695c96..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|CHASE_AUTOFS, &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/sysupdate/sysupdate.c b/src/sysupdate/sysupdate.c index a7b278f7e7..692291fcfe 100644 --- a/src/sysupdate/sysupdate.c +++ b/src/sysupdate/sysupdate.c @@ -1557,7 +1557,7 @@ static int verb_components(int argc, char **argv, void *userdata) { _cleanup_closedir_ DIR *d = NULL; _cleanup_free_ char *p = NULL; - r = chase_and_opendir(*i, arg_root, CHASE_PREFIX_ROOT|CHASE_AUTOFS, &p, &d); + r = chase_and_opendir(*i, arg_root, CHASE_PREFIX_ROOT, &p, &d); if (r == -ENOENT) continue; if (r < 0) diff --git a/src/test/test-chase-manual.c b/src/test/test-chase-manual.c index c3327cd24e..376cd12c42 100644 --- a/src/test/test-chase-manual.c +++ b/src/test/test-chase-manual.c @@ -24,7 +24,8 @@ static int parse_argv(int argc, char *argv[]) { { "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT }, { "nonexistent", no_argument, NULL, CHASE_NONEXISTENT }, - { "autofs", no_argument, NULL, CHASE_AUTOFS }, + { "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 }, @@ -60,7 +61,8 @@ static int parse_argv(int argc, char *argv[]) { case CHASE_PREFIX_ROOT: case CHASE_NONEXISTENT: - case CHASE_AUTOFS: + case CHASE_NO_AUTOFS: + case CHASE_TRIGGER_AUTOFS: case CHASE_SAFE: case CHASE_TRAIL_SLASH: case CHASE_STEP: diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 62710a5bcc..060914f27c 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1082,7 +1082,7 @@ static int path_open_parent_safe(const char *path, bool allow_failure) { path, allow_failure ? ", ignoring" : ""); - r = chase(dn, arg_root, allow_failure ? CHASE_SAFE|CHASE_AUTOFS : CHASE_SAFE|CHASE_WARN|CHASE_AUTOFS, NULL, &fd); + r = chase(dn, arg_root, allow_failure ? CHASE_SAFE : CHASE_SAFE|CHASE_WARN, NULL, &fd); if (r == -ENOLINK) /* Unsafe symlink: already covered by CHASE_WARN */ return r; if (r < 0) @@ -1107,7 +1107,7 @@ static int path_open_safe(const char *path) { if (!path_is_normalized(path)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to open invalid path '%s'.", path); - r = chase(path, arg_root, CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW|CHASE_AUTOFS, NULL, &fd); + r = chase(path, arg_root, CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL, &fd); if (r == -ENOLINK) return r; /* Unsafe symlink: already covered by CHASE_WARN */ if (r < 0) @@ -2162,7 +2162,7 @@ static int empty_directory( assert(i); assert(i->type == EMPTY_DIRECTORY); - r = chase(path, arg_root, CHASE_SAFE|CHASE_WARN|CHASE_AUTOFS, NULL, &fd); + r = chase(path, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd); if (r == -ENOLINK) /* Unsafe symlink: already covered by CHASE_WARN */ return r; if (r == -ENOENT) { @@ -2406,7 +2406,7 @@ static int create_symlink(Context *c, Item *i) { assert(i); if (i->ignore_if_target_missing) { - r = chase(i->argument, arg_root, CHASE_SAFE|CHASE_PREFIX_ROOT|CHASE_NOFOLLOW|CHASE_AUTOFS, /* ret_path = */ NULL, /* ret_fd = */ NULL); + r = chase(i->argument, arg_root, CHASE_SAFE|CHASE_PREFIX_ROOT|CHASE_NOFOLLOW, /* ret_path = */ NULL, /* ret_fd = */ NULL); if (r == -ENOENT) { /* Silently skip over lines where the source file is missing. */ log_info("Symlink source path '%s/%s' does not exist, skipping line.", @@ -3232,7 +3232,7 @@ static int process_item( path = _path; } - r = chase(path, arg_root, CHASE_NONEXISTENT|CHASE_WARN|CHASE_AUTOFS, NULL, NULL); + r = chase(path, arg_root, CHASE_NO_AUTOFS|CHASE_NONEXISTENT|CHASE_WARN, NULL, NULL); if (r == -EREMOTE) { log_notice_errno(r, "Skipping %s", i->path); /* We log the configured path, to not confuse the user. */ return 0;