diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/path-util.h | 12 | ||||
-rw-r--r-- | src/basic/virt.c | 27 | ||||
-rw-r--r-- | src/core/mount.c | 72 | ||||
-rw-r--r-- | src/core/target.c | 5 | ||||
-rw-r--r-- | src/shared/generator.c | 2 |
5 files changed, 76 insertions, 42 deletions
diff --git a/src/basic/path-util.h b/src/basic/path-util.h index d548f0c345..349cdac7d6 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -66,6 +66,18 @@ static inline bool path_equal_ptr(const char *a, const char *b) { _found; \ }) +#define PATH_STARTSWITH_SET(p, ...) \ + ({ \ + char **s; \ + bool _found = false; \ + STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \ + if (path_startswith(p, *s)) { \ + _found = true; \ + break; \ + } \ + _found; \ + }) + int path_strv_make_absolute_cwd(char **l); char** path_strv_resolve(char **l, const char *root); char** path_strv_resolve_uniq(char **l, const char *root); diff --git a/src/basic/virt.c b/src/basic/virt.c index d8d57381ad..9b7eb71319 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -25,15 +25,16 @@ #include "alloc-util.h" #include "dirent-util.h" +#include "env-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "macro.h" #include "process-util.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "virt.h" -#include "env-util.h" static int detect_vm_cpuid(void) { @@ -556,16 +557,30 @@ int running_in_userns(void) { } int running_in_chroot(void) { - int ret; + _cleanup_free_ char *self_mnt = NULL, *pid1_mnt = NULL; + int r; + + /* Try to detect whether we are running in a chroot() environment. Specifically, check whether we have a + * different root directory than PID 1, even though we live in the same mount namespace as it. */ if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0) return 0; - ret = files_same("/proc/1/root", "/"); - if (ret < 0) - return ret; + r = files_same("/proc/1/root", "/"); + if (r < 0) + return r; + if (r > 0) + return 0; + + r = readlink_malloc("/proc/self/ns/mnt", &self_mnt); + if (r < 0) + return r; + + r = readlink_malloc("/proc/1/ns/mnt", &pid1_mnt); + if (r < 0) + return r; - return ret == 0; + return streq(self_mnt, pid1_mnt); /* Only if we live in the same namespace! */ } static const char *const virtualization_table[_VIRTUALIZATION_MAX] = { diff --git a/src/core/mount.c b/src/core/mount.c index 0c4d061c27..997dbe3837 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -387,19 +387,35 @@ static int mount_add_quota_links(Mount *m) { return 0; } -static bool should_umount(Mount *m) { +static bool mount_is_extrinsic(Mount *m) { MountParameters *p; + assert(m); - if (PATH_IN_SET(m->where, "/", "/usr") || - path_startswith(m->where, "/run/initramfs")) - return false; + /* Returns true for all units that are "magic" and should be excluded from the usual start-up and shutdown + * dependencies. We call them "extrinsic" here, as they are generally mounted outside of the systemd dependency + * logic. We shouldn't attempt to manage them ourselves but it's fine if the user operates on them with us. */ + + if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) /* We only automatically manage mounts if we are in system mode */ + return true; + + if (PATH_IN_SET(m->where, /* Don't bother with the OS data itself */ + "/", + "/usr")) + return true; + if (PATH_STARTSWITH_SET(m->where, + "/run/initramfs", /* This should stay around from before we boot until after we shutdown */ + "/proc", /* All of this is API VFS */ + "/sys", /* … dito … */ + "/dev")) /* … dito … */ + return true; + + /* If this is an initrd mount, and we are not in the initrd, then leave this around forever, too. */ p = get_mount_parameters(m); - if (p && fstab_test_option(p->options, "x-initrd.mount\0") && - !in_initrd()) - return false; + if (p && fstab_test_option(p->options, "x-initrd.mount\0") && !in_initrd()) + return true; - return true; + return false; } static int mount_add_default_dependencies(Mount *m) { @@ -412,20 +428,10 @@ static int mount_add_default_dependencies(Mount *m) { if (!UNIT(m)->default_dependencies) return 0; - if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) - return 0; - - /* We do not add any default dependencies to /, /usr or - * /run/initramfs/, since they are guaranteed to stay - * mounted the whole time, since our system is on it. - * Also, don't bother with anything mounted below virtual - * file systems, it's also going to be virtual, and hence - * not worth the effort. */ - if (PATH_IN_SET(m->where, "/", "/usr") || - path_startswith(m->where, "/run/initramfs") || - path_startswith(m->where, "/proc") || - path_startswith(m->where, "/sys") || - path_startswith(m->where, "/dev")) + /* We do not add any default dependencies to /, /usr or /run/initramfs/, since they are guaranteed to stay + * mounted the whole time, since our system is on it. Also, don't bother with anything mounted below virtual + * file systems, it's also going to be virtual, and hence not worth the effort. */ + if (mount_is_extrinsic(m)) return 0; p = get_mount_parameters(m); @@ -462,11 +468,9 @@ static int mount_add_default_dependencies(Mount *m) { if (r < 0) return r; - if (should_umount(m)) { - r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); - if (r < 0) - return r; - } + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); + if (r < 0) + return r; return 0; } @@ -688,6 +692,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { "%sOptions: %s\n" "%sFrom /proc/self/mountinfo: %s\n" "%sFrom fragment: %s\n" + "%sExtrinsic: %s\n" "%sDirectoryMode: %04o\n" "%sSloppyOptions: %s\n" "%sLazyUnmount: %s\n" @@ -700,6 +705,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { prefix, p ? strna(p->options) : "n/a", prefix, yes_no(m->from_proc_self_mountinfo), prefix, yes_no(m->from_fragment), + prefix, yes_no(mount_is_extrinsic(m)), prefix, m->directory_mode, prefix, yes_no(m->sloppy_options), prefix, yes_no(m->lazy_unmount), @@ -1420,7 +1426,7 @@ static int mount_setup_unit( goto fail; } - if (MANAGER_IS_SYSTEM(m)) { + if (!mount_is_extrinsic(MOUNT(u))) { const char* target; target = mount_needs_network(options, fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; @@ -1428,11 +1434,9 @@ static int mount_setup_unit( if (r < 0) goto fail; - if (should_umount(MOUNT(u))) { - r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); - if (r < 0) - goto fail; - } + r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); + if (r < 0) + goto fail; } unit_add_to_load_queue(u); @@ -1448,7 +1452,7 @@ static int mount_setup_unit( } } - if (MANAGER_IS_SYSTEM(m) && + if (!mount_is_extrinsic(MOUNT(u)) && mount_needs_network(options, fstype)) { /* _netdev option may have shown up late, or on a * remount. Add remote-fs dependencies, even though diff --git a/src/core/target.c b/src/core/target.c index 765c1f3fa4..ff0d764fb5 100644 --- a/src/core/target.c +++ b/src/core/target.c @@ -75,8 +75,11 @@ static int target_add_default_dependencies(Target *t) { return r; } + if (unit_has_name(UNIT(t), SPECIAL_SHUTDOWN_TARGET)) + return 0; + /* Make sure targets are unloaded on shutdown */ - return unit_add_dependency_by_name(UNIT(t), UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); + return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); } static int target_load(Unit *u) { diff --git a/src/shared/generator.c b/src/shared/generator.c index 70afc6a285..9a069b2f97 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -65,7 +65,7 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) { "Description=File System Check on %2$s\n" "DefaultDependencies=no\n" "BindsTo=%3$s\n" - "After=initrd-root-device.target local-fs-pre.target\n" + "After=initrd-root-device.target local-fs-pre.target %3$s\n" "Before=shutdown.target\n" "\n" "[Service]\n" |