]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
chase: trigger automount only when explicitly requested 38641/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Aug 2025 16:22:30 +0000 (17:22 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 19 Aug 2025 17:32:02 +0000 (02:32 +0900)
Since c5de7b14ae2e08d267d8d75bc88934ac6aa7dcd6
file searching implies a new mount api syscall by default,
to trigger automounts.

But, this is not necessary in most cases, e.g. when chasing
syspath in sd-device (actually this causes regression in umockdev,
see https://github.com/martinpitt/umockdev/issues/271).
Another example is reading unit files, especially .network files,
as automount may trigger mounting network filesystems...

Also, when this is used in NSS plugins, programs that load the
plugins may fail because of spuriously configured seccomp. See #38565.

Let's not trigger automount by default, and do only when explicitly
requested.

This introduces CHASE_TRIGGER_AUTOFS, and use it in
- service manager,
- bootctl and finding ESP/xbootldr,
- sysupdate,
- mountfsd,
- systemd-mount.

There may be several more places we should trigger automount, but let's
do that later.

Follow-up for c5de7b14ae2e08d267d8d75bc88934ac6aa7dcd6.
Fixes #38565.
Replaces #38569.

Co-authored-by: Luca Boccassi <luca.boccassi@gmail.com>
16 files changed:
mkosi/mkosi.sanitizers/mkosi.postinst
src/basic/chase.c
src/basic/chase.h
src/bootctl/bootctl-install.c
src/bootctl/bootctl-status.c
src/core/exec-invoke.c
src/core/mount.c
src/core/namespace.c
src/core/service.c
src/mount/mount-tool.c
src/mountfsd/mountwork.c
src/shared/find-esp.c
src/sysupdate/sysupdate-resource.c
src/sysupdate/sysupdate-transfer.c
src/test/test-chase-manual.c
test/units/TEST-74-AUX-UTILS.userdbctl.sh

index 9806f7aab37d1b55c3668c4470f971d6cebaa353..04c019cf2cca7be4d122055065c6926b53face25 100755 (executable)
@@ -62,6 +62,7 @@ wrap=(
     findmnt
     getent
     getfacl
+    groups
     id
     integritysetup
     iscsid
index 9219209421cadfba25ac4fd4037a87d5baa6ce30..ddef19448741dc2e2eac9a9a849608e08116cc6b 100644 (file)
@@ -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;
index 36632c8a325a9de46b11c7ccfe79a66c792f23a1..554ab6cadd212c0ac68f9051822ef457555d967d 100644 (file)
@@ -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);
index ddeed5ecf10d88e4f0586ba1c3d470b14e0cea54..27ec4cf0fea9a23cf1b5a738a3487195f38e5e67 100644 (file)
@@ -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)
index 2c3208a471b5dc6f5eb6208f905fb9895a226341..81fdeed64e6b5dfa065d0ece5d809921bdb1e8f0 100644 (file)
@@ -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;
index 1e2945eb910ef1dcf2111a829f6889a66e977629..72050aad694d862bdc8d346a67e8175c421dd0fd 100644 (file)
@@ -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)
index e1e6cf2b2fed829eec83c6c23dc10289f1d8efa2..36a877ab148372ab0dbb946e1c3ab9a111c8a7e2 100644 (file)
@@ -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;
index 644614a1845ec0c82be56c1cf16920ded6429e0c..283a1108cefc44bac0ca712cd3745fb40abf605d 100644 (file)
@@ -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;
index d94162ead0be5738fe1c04691b27bc9d5ebdd828..c8cda0609942fcda179a8d62828976d9c3fdd71c 100644 (file)
@@ -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;
index a684c0bef8af2e3fffec8021683117712b35bdf2..c8bb9a192bd613596d8eede49304754577ed501f 100644 (file)
@@ -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;
index 207609d232d184701146eea1f58f614e81c3ef49..bfb8c05c22cdd4971958e7845d173154d10d9664 100644 (file)
@@ -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);
 
index eeec050b60d0ce7f7c970a3f5f4dbc6f17a207cc..eabc3efc5ecd73ec520ef4fb1bd25a0ff2270e52 100644 (file)
@@ -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);
 
index 549edcf9d4c12afdefad4d71064f70f37ba8e25d..b0fa799fd1f45c2312d25b152aa844e01744c772 100644 (file)
@@ -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);
index 82fd931dab75f311846a1f21f5ab268670eaa3f9..cb57d4af093fba4251e72da06d9803156cc4b030 100644 (file)
@@ -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);
 
index 03c0a245bd4b4c59fc75e0d00cca699e70800852..376cd12c42628832474b9dc00e6c27c9f0a18bab 100644 (file)
@@ -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:
index 55927778492902eeb071f232e207d7d2d48071ec..53edb962e7cbdeb4d08837ac865cb58eecaebdf8 100755 (executable)
@@ -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