summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorLuca Boccassi <bluca@debian.org>2023-07-22 23:45:16 +0200
committerLuca Boccassi <bluca@debian.org>2023-07-24 11:39:14 +0200
commitb12d41a8bb7c99f7d7a1c7821a886d98b42d9ce0 (patch)
treea3134b59f82a5442d49bb07c03c23e257b8b59ce /src/shared
parentpo: Translated using Weblate (Czech) (diff)
downloadsystemd-b12d41a8bb7c99f7d7a1c7821a886d98b42d9ce0.tar.xz
systemd-b12d41a8bb7c99f7d7a1c7821a886d98b42d9ce0.zip
switch-root: use MS_REC for /run, unless we are soft-rebooting
There are applications that rely on mounts under /run surviving the switch from initrd to rootfs, so use MS_REC unless we are soft rebooting. Follow-up for 7c764d45997721705e43ac66fbb5a56747d00d40 Fixes https://github.com/systemd/systemd/issues/28452
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/switch-root.c23
-rw-r--r--src/shared/switch-root.h5
2 files changed, 19 insertions, 9 deletions
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index 070d5bd908..37395e02ad 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -30,17 +30,23 @@ int switch_root(const char *new_root,
const char *old_root_after, /* path below the new root, where to place the old root after the transition; may be NULL to unmount it */
SwitchRootFlags flags) {
+ /* Stuff mounted below /run we don't save on soft reboot, as it might have lost its relevance, i.e.
+ * credentials, removable media and such, we rather want that the new boot mounts this fresh.
+ * But on the switch from initrd we do use MS_REC, as it is expected that mounts set up in /run
+ * are maintained. */
+ unsigned long run_mount_flags = MS_BIND|(!FLAGS_SET(flags, SWITCH_ROOT_SKIP_RECURSIVE_RUN) ? MS_REC : 0);
struct {
const char *path;
unsigned long mount_flags;
+ bool skip_if_run_is_rec; /* For child mounts of /run, if it's moved recursively no need to handle */
} transfer_table[] = {
- { "/dev", MS_BIND|MS_REC }, /* Recursive, because we want to save the original /dev/shm + /dev/pts and similar */
- { "/sys", MS_BIND|MS_REC }, /* Similar, we want to retain various API VFS, or the cgroupv1 /sys/fs/cgroup/ tree */
- { "/proc", MS_BIND|MS_REC }, /* Similar */
- { "/run", MS_BIND }, /* Stuff mounted below this we don't save, as it might have lost its relevance, i.e. credentials, removable media and such, we rather want that the new boot mounts this fresh */
- { SYSTEM_CREDENTIALS_DIRECTORY, MS_BIND }, /* Credentials passed into the system should survive */
- { ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY, MS_BIND }, /* Similar */
- { "/run/host", MS_BIND|MS_REC }, /* Host supplied hierarchy should also survive */
+ { "/dev", MS_BIND|MS_REC, false }, /* Recursive, because we want to save the original /dev/shm + /dev/pts and similar */
+ { "/sys", MS_BIND|MS_REC, false }, /* Similar, we want to retain various API VFS, or the cgroupv1 /sys/fs/cgroup/ tree */
+ { "/proc", MS_BIND|MS_REC, false }, /* Similar */
+ { "/run", run_mount_flags, false }, /* Recursive except on soft reboot, see above */
+ { SYSTEM_CREDENTIALS_DIRECTORY, MS_BIND, true }, /* Credentials passed into the system should survive */
+ { ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY, MS_BIND, true }, /* Similar */
+ { "/run/host", MS_BIND|MS_REC, true }, /* Host supplied hierarchy should also survive */
};
_cleanup_close_ int old_root_fd = -EBADF, new_root_fd = -EBADF;
@@ -112,6 +118,9 @@ int switch_root(const char *new_root,
FOREACH_ARRAY(transfer, transfer_table, ELEMENTSOF(transfer_table)) {
_cleanup_free_ char *chased = NULL;
+ if (transfer->skip_if_run_is_rec && !FLAGS_SET(flags, SWITCH_ROOT_SKIP_RECURSIVE_RUN))
+ continue;
+
if (access(transfer->path, F_OK) < 0) {
log_debug_errno(errno, "Path '%s' to move to target root directory, not found, ignoring: %m", transfer->path);
continue;
diff --git a/src/shared/switch-root.h b/src/shared/switch-root.h
index 79e47c67f4..78d62f28e0 100644
--- a/src/shared/switch-root.h
+++ b/src/shared/switch-root.h
@@ -4,8 +4,9 @@
#include <stdbool.h>
typedef enum SwitchRootFlags {
- SWITCH_ROOT_DESTROY_OLD_ROOT = 1 << 0, /* rm -rf old root when switching – under the condition that it is backed by non-persistent tmpfs/ramfs/… */
- SWITCH_ROOT_DONT_SYNC = 1 << 1, /* don't call sync() immediately before switching root */
+ SWITCH_ROOT_DESTROY_OLD_ROOT = 1 << 0, /* rm -rf old root when switching – under the condition that it is backed by non-persistent tmpfs/ramfs/… */
+ SWITCH_ROOT_DONT_SYNC = 1 << 1, /* don't call sync() immediately before switching root */
+ SWITCH_ROOT_SKIP_RECURSIVE_RUN = 1 << 2, /* move /run without MS_REC */
} SwitchRootFlags;
int switch_root(const char *new_root, const char *old_root_after, SwitchRootFlags flags);