mirror of
https://github.com/systemd/systemd
synced 2025-10-06 00:13:24 +02:00
chase: trigger automount only when explicitly requested
Sincec5de7b14ae
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 forc5de7b14ae
. Fixes #38565. Replaces #38569. Co-authored-by: Luca Boccassi <luca.boccassi@gmail.com>
This commit is contained in:
@@ -62,6 +62,7 @@ wrap=(
|
|||||||
findmnt
|
findmnt
|
||||||
getent
|
getent
|
||||||
getfacl
|
getfacl
|
||||||
|
groups
|
||||||
id
|
id
|
||||||
integritysetup
|
integritysetup
|
||||||
iscsid
|
iscsid
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#define CHASE_NO_SHORTCUT_MASK \
|
#define CHASE_NO_SHORTCUT_MASK \
|
||||||
(CHASE_NONEXISTENT | \
|
(CHASE_NONEXISTENT | \
|
||||||
CHASE_NO_AUTOFS | \
|
CHASE_NO_AUTOFS | \
|
||||||
|
CHASE_TRIGGER_AUTOFS | \
|
||||||
CHASE_SAFE | \
|
CHASE_SAFE | \
|
||||||
CHASE_STEP | \
|
CHASE_STEP | \
|
||||||
CHASE_PROHIBIT_SYMLINKS | \
|
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()
|
/* 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
|
* 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
|
* 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.
|
* 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_PREFIX_ROOT));
|
||||||
assert(!FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY|CHASE_MUST_BE_REGULAR));
|
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_STEP|CHASE_EXTRACT_FILENAME));
|
||||||
|
assert(!FLAGS_SET(flags, CHASE_NO_AUTOFS|CHASE_TRIGGER_AUTOFS));
|
||||||
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
|
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
|
||||||
|
|
||||||
if (FLAGS_SET(flags, CHASE_STEP))
|
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. */
|
/* 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 < 0) {
|
||||||
if (r != -ENOENT)
|
if (r != -ENOENT)
|
||||||
return r;
|
return r;
|
||||||
|
@@ -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_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_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_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_TRIGGER_AUTOFS = 1 << 3, /* Use open_tree() rather than openat() to trigger autofs mount */
|
||||||
CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */
|
CHASE_SAFE = 1 << 4, /* Return -EPERM if we ever traverse from unprivileged to privileged files or directories */
|
||||||
CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */
|
CHASE_TRAIL_SLASH = 1 << 5, /* Any trailing slash will be preserved */
|
||||||
CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most component. With ret_fd, when the path's
|
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. */
|
* 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. */
|
* 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. */
|
* relative to the given directory fd instead of root. */
|
||||||
CHASE_PROHIBIT_SYMLINKS = 1 << 9, /* Refuse all symlinks */
|
CHASE_PROHIBIT_SYMLINKS = 1 << 10, /* Refuse all symlinks */
|
||||||
CHASE_PARENT = 1 << 10, /* Chase the parent directory of the given path. Note that the
|
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
|
* full path is still stored in ret_path and only the returned
|
||||||
* file descriptor will point to the parent directory. Note that
|
* file descriptor will point to the parent directory. Note that
|
||||||
* the result path is the root or '.', then the file descriptor
|
* the result path is the root or '.', then the file descriptor
|
||||||
* also points to the result path even if this flag is set.
|
* also points to the result path even if this flag is set.
|
||||||
* When this specified, chase() will succeed with 1 even if the
|
* When this specified, chase() will succeed with 1 even if the
|
||||||
* file points to the last path component does not exist. */
|
* file points to the last path component does not exist. */
|
||||||
CHASE_MKDIR_0755 = 1 << 11, /* Create any missing directories in the given path. */
|
CHASE_MKDIR_0755 = 1 << 12, /* Create any missing directories in the given path. */
|
||||||
CHASE_EXTRACT_FILENAME = 1 << 12, /* Only return the last component of the resolved path */
|
CHASE_EXTRACT_FILENAME = 1 << 13, /* 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_DIRECTORY = 1 << 14, /* 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_MUST_BE_REGULAR = 1 << 15, /* Fail if returned inode fd is not a regular file */
|
||||||
} ChaseFlags;
|
} ChaseFlags;
|
||||||
|
|
||||||
bool unsafe_transition(const struct stat *a, const struct stat *b);
|
bool unsafe_transition(const struct stat *a, const struct stat *b);
|
||||||
|
@@ -343,7 +343,7 @@ static int update_efi_boot_binaries(const char *esp_path, const char *source_pat
|
|||||||
assert(esp_path);
|
assert(esp_path);
|
||||||
assert(source_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)
|
if (r == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@@ -396,10 +396,10 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
|
|||||||
if (!p)
|
if (!p)
|
||||||
return log_oom();
|
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 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)
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r,
|
return log_error_errno(r,
|
||||||
"Failed to resolve path %s%s%s: %m",
|
"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)
|
if (!q)
|
||||||
return log_oom();
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", q, esp_path);
|
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);
|
v = strjoina("/EFI/BOOT/BOOT", e);
|
||||||
ascii_strupper(strrchr(v, '/') + 1);
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", v, esp_path);
|
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;
|
_cleanup_free_ char *path = NULL;
|
||||||
int r;
|
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 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)
|
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) {
|
if (r == -ENOENT && arg_graceful) {
|
||||||
log_debug("Source directory does not exist, ignoring.");
|
log_debug("Source directory does not exist, ignoring.");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -634,7 +634,7 @@ static int install_secure_boot_auto_enroll(const char *esp, X509 *certificate, E
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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)
|
if (keys_fd < 0)
|
||||||
return log_error_errno(keys_fd, "Failed to chase loader/keys/auto in the ESP: %m");
|
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;
|
uint16_t slot;
|
||||||
int r;
|
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)
|
if (r == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@@ -1097,7 +1097,7 @@ static int remove_boot_efi(const char *esp_path) {
|
|||||||
_cleanup_free_ char *p = NULL;
|
_cleanup_free_ char *p = NULL;
|
||||||
int r, c = 0;
|
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)
|
if (r == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@@ -222,7 +222,7 @@ static int enumerate_binaries(
|
|||||||
assert(previous);
|
assert(previous);
|
||||||
assert(is_first);
|
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)
|
if (r == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@@ -693,7 +693,7 @@ static void deref_unlink_file(Hashmap **known_files, const char *fn, const char
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (arg_dry_run) {
|
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)
|
if (r < 0)
|
||||||
log_info_errno(r, "Unable to determine whether \"%s\" exists, ignoring: %m", fn);
|
log_info_errno(r, "Unable to determine whether \"%s\" exists, ignoring: %m", fn);
|
||||||
else
|
else
|
||||||
@@ -701,7 +701,7 @@ static void deref_unlink_file(Hashmap **known_files, const char *fn, const char
|
|||||||
return;
|
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)
|
if (r >= 0)
|
||||||
log_info("Removed \"%s\"", path);
|
log_info("Removed \"%s\"", path);
|
||||||
else if (r != -ENOENT)
|
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;
|
_cleanup_free_ char *d = NULL;
|
||||||
if (path_extract_directory(fn, &d) >= 0 && !path_equal(d, "/")) {
|
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))
|
if (r < 0 && !IN_SET(r, -ENOTEMPTY, -ENOENT))
|
||||||
log_warning_errno(r, "Failed to remove directory \"%s\", ignoring: %m", d);
|
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)
|
if (arg_dry_run)
|
||||||
log_info("Would remove \"%s\"", e->path);
|
log_info("Would remove \"%s\"", e->path);
|
||||||
else {
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to remove \"%s\": %m", e->path);
|
return log_error_errno(r, "Failed to remove \"%s\": %m", e->path);
|
||||||
|
|
||||||
@@ -862,7 +862,7 @@ static int cleanup_orphaned_files(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to count files in %s: %m", root);
|
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);
|
O_DIRECTORY|O_CLOEXEC, &full);
|
||||||
if (dir_fd == -ENOENT)
|
if (dir_fd == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -3985,7 +3985,7 @@ static int apply_working_directory(
|
|||||||
|
|
||||||
r = chase(wd,
|
r = chase(wd,
|
||||||
runtime->ephemeral_copy ?: context->root_directory,
|
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,
|
/* ret_path= */ NULL,
|
||||||
&dfd);
|
&dfd);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
|
@@ -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
|
/* 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
|
* couldn't support that reasonably: the mounts in /proc/self/mountinfo would not be recognizable to
|
||||||
* us anymore. */
|
* 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) {
|
if (fd == -EREMCHG) {
|
||||||
r = unit_log_noncanonical_mount_path(UNIT(m), m->where);
|
r = unit_log_noncanonical_mount_path(UNIT(m), m->where);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@@ -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
|
* 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. */
|
* 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)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to chase symlinks '%s': %m", mount_entry_path(m));
|
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 */
|
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));
|
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) {
|
if (r == -ENOENT && m->ignore) {
|
||||||
log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m));
|
log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m));
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3434,7 +3434,7 @@ static int is_extension_overlay(const char *path, int fd) {
|
|||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
if (fd < 0) {
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
fd = dfd;
|
fd = dfd;
|
||||||
|
@@ -5622,7 +5622,7 @@ int service_determine_exec_selinux_label(Service *s, char **ret) {
|
|||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
|
|
||||||
_cleanup_free_ char *path = NULL;
|
_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) {
|
if (r < 0) {
|
||||||
log_unit_debug_errno(UNIT(s), r, "Failed to resolve service binary '%s', ignoring.", c->path);
|
log_unit_debug_errno(UNIT(s), r, "Failed to resolve service binary '%s', ignoring.", c->path);
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
|
@@ -91,7 +91,7 @@ static int parse_where(const char *input, char **ret_where) {
|
|||||||
assert(ret_where);
|
assert(ret_where);
|
||||||
|
|
||||||
if (arg_transport == BUS_TRANSPORT_LOCAL && arg_canonicalize) {
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to make path %s absolute: %m", input);
|
return log_error_errno(r, "Failed to make path %s absolute: %m", input);
|
||||||
} else {
|
} else {
|
||||||
@@ -476,7 +476,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arg_transport == BUS_TRANSPORT_LOCAL && arg_canonicalize) {
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to chase path '%s': %m", p);
|
return log_error_errno(r, "Failed to chase path '%s': %m", p);
|
||||||
} else {
|
} else {
|
||||||
@@ -1103,7 +1103,7 @@ static int action_umount(sd_bus *bus, int argc, char **argv) {
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_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) {
|
if (r < 0) {
|
||||||
RET_GATHER(ret, log_error_errno(r, "Failed to chase path '%s': %m", u));
|
RET_GATHER(ret, log_error_errno(r, "Failed to chase path '%s': %m", u));
|
||||||
continue;
|
continue;
|
||||||
|
@@ -176,7 +176,7 @@ static int verify_trusted_image_fd_by_path(int fd) {
|
|||||||
struct stat stb;
|
struct stat stb;
|
||||||
const char *e;
|
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)
|
if (r == -ENOENT)
|
||||||
continue;
|
continue;
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@@ -194,7 +194,7 @@ static int verify_trusted_image_fd_by_path(int fd) {
|
|||||||
if (!filename_is_valid(e))
|
if (!filename_is_valid(e))
|
||||||
continue;
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Couldn't verify that specified image '%s' is in search path '%s': %m", p, s);
|
return log_error_errno(r, "Couldn't verify that specified image '%s' is in search path '%s': %m", p, s);
|
||||||
|
|
||||||
|
@@ -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
|
/* 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. */
|
* 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)
|
if (r < 0)
|
||||||
return log_full_errno((searching && r == -ENOENT) ||
|
return log_full_errno((searching && r == -ENOENT) ||
|
||||||
(unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR,
|
(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",
|
"$SYSTEMD_ESP_PATH does not refer to an absolute path, refusing to use it: %s",
|
||||||
path);
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to resolve path %s: %m", path);
|
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(rfd >= 0 || rfd == AT_FDCWD);
|
||||||
assert(path);
|
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)
|
if (r < 0)
|
||||||
return log_full_errno((searching && r == -ENOENT) ||
|
return log_full_errno((searching && r == -ENOENT) ||
|
||||||
(unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR,
|
(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",
|
"$SYSTEMD_XBOOTLDR_PATH does not refer to an absolute path, refusing to use it: %s",
|
||||||
path);
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to resolve path %s: %m", p);
|
return log_error_errno(r, "Failed to resolve path %s: %m", p);
|
||||||
|
|
||||||
|
@@ -660,7 +660,7 @@ int resource_resolve_path(
|
|||||||
_cleanup_free_ char *resolved = NULL;
|
_cleanup_free_ char *resolved = NULL;
|
||||||
struct stat st;
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to resolve '%s': %m", rr->path);
|
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)) {
|
} else if (RESOURCE_IS_FILESYSTEM(rr->type)) {
|
||||||
_cleanup_free_ char *resolved = NULL, *relative_to = NULL;
|
_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) {
|
if (rr->path_relative_to == PATH_RELATIVE_TO_EXPLICIT) {
|
||||||
assert(relative_to_directory);
|
assert(relative_to_directory);
|
||||||
|
@@ -1498,7 +1498,7 @@ int transfer_install_instance(
|
|||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
|
|
||||||
if (resolve_link_path && root) {
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to resolve current symlink path '%s': %m", link_path);
|
return log_error_errno(r, "Failed to resolve current symlink path '%s': %m", link_path);
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
{ "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT },
|
{ "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT },
|
||||||
{ "nonexistent", no_argument, NULL, CHASE_NONEXISTENT },
|
{ "nonexistent", no_argument, NULL, CHASE_NONEXISTENT },
|
||||||
{ "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS },
|
{ "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS },
|
||||||
|
{ "trigger-autofs", no_argument, NULL, CHASE_TRIGGER_AUTOFS },
|
||||||
{ "safe", no_argument, NULL, CHASE_SAFE },
|
{ "safe", no_argument, NULL, CHASE_SAFE },
|
||||||
{ "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH },
|
{ "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH },
|
||||||
{ "step", no_argument, NULL, CHASE_STEP },
|
{ "step", no_argument, NULL, CHASE_STEP },
|
||||||
@@ -61,6 +62,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
case CHASE_PREFIX_ROOT:
|
case CHASE_PREFIX_ROOT:
|
||||||
case CHASE_NONEXISTENT:
|
case CHASE_NONEXISTENT:
|
||||||
case CHASE_NO_AUTOFS:
|
case CHASE_NO_AUTOFS:
|
||||||
|
case CHASE_TRIGGER_AUTOFS:
|
||||||
case CHASE_SAFE:
|
case CHASE_SAFE:
|
||||||
case CHASE_TRAIL_SLASH:
|
case CHASE_TRAIL_SLASH:
|
||||||
case CHASE_STEP:
|
case CHASE_STEP:
|
||||||
|
@@ -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 root -j | userdbctl -F- group | cmp - <(userdbctl group root)
|
||||||
userdbctl group systemd-network -j | userdbctl -F- group | cmp - <(userdbctl group systemd-network)
|
userdbctl group systemd-network -j | userdbctl -F- group | cmp - <(userdbctl group systemd-network)
|
||||||
userdbctl group 65534 -j | userdbctl -F- group | cmp - <(userdbctl group 65534)
|
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
|
||||||
|
Reference in New Issue
Block a user