chase: trigger automount only when explicitly requested
Sincec5de7b14aefile 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 forc5de7b14ae. Fixes #38565. Replaces #38569. Co-authored-by: Luca Boccassi <luca.boccassi@gmail.com>
This commit is contained in:
co-authored by
Luca Boccassi
parent
9dcd034085
commit
4279336618
+4
-2
@@ -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;
|
||||
|
||||
+13
-12
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user