From 378a6b8b92701b3315b9e13b51ad367a60b768f9 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 22 Jul 2023 22:45:16 +0100 Subject: [PATCH] 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 --- src/core/main.c | 3 ++- src/shared/switch-root.c | 7 ++++++- src/shared/switch-root.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 7094be8dba064..361fbff7c15b8 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1884,7 +1884,8 @@ static int do_reexecute( if (switch_root_dir) { r = switch_root(/* new_root= */ switch_root_dir, /* old_root_after= */ NULL, - /* flags= */ objective == MANAGER_SWITCH_ROOT ? SWITCH_ROOT_DESTROY_OLD_ROOT : 0); + /* flags= */ (objective == MANAGER_SWITCH_ROOT ? SWITCH_ROOT_DESTROY_OLD_ROOT : 0) | + (objective == MANAGER_SOFT_REBOOT ? SWITCH_ROOT_SOFT_REBOOT : 0)); if (r < 0) log_error_errno(r, "Failed to switch root, trying to continue: %m"); } diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index 070d5bd908b3c..175d75038794c 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -30,6 +30,11 @@ 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_SOFT_REBOOT) ? MS_REC : 0); struct { const char *path; unsigned long mount_flags; @@ -37,7 +42,7 @@ int switch_root(const char *new_root, { "/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 */ + { "/run", run_mount_flags}, /* Recursive except on soft reboot, see above */ { 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 */ diff --git a/src/shared/switch-root.h b/src/shared/switch-root.h index 79e47c67f471b..5dcc0c583270d 100644 --- a/src/shared/switch-root.h +++ b/src/shared/switch-root.h @@ -6,6 +6,7 @@ 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_SOFT_REBOOT = 1 << 2, /* move /run without MS_REC */ } SwitchRootFlags; int switch_root(const char *new_root, const char *old_root_after, SwitchRootFlags flags);