From: Lennart Poettering Date: Mon, 15 May 2023 19:25:12 +0000 (+0200) Subject: switch-root: when switching root via MS_MOVE unmount all remaining mounts first X-Git-Tag: v254-rc1~441^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=268d1244e87a35ff8dff56c92ef375ebf69d462e;p=thirdparty%2Fsystemd.git switch-root: when switching root via MS_MOVE unmount all remaining mounts first Let's try to unmount anything left, since if we don't they will remain as "shadow" mounts, hidden underneath our new root. This is only necessary when we transition into a new root via MS_MOVE. If we do so via pivot_root() this is not necessary as the kernel will get rid of the mounts anyway for us. --- diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index 1ee06c8ee4d..2431facba00 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -114,6 +114,14 @@ int switch_root(const char *new_root, if (r < 0) { log_debug_errno(r, "Pivoting root file system failed, moving mounts instead: %m"); + /* If we have to use MS_MOVE let's first try to get rid of *all* mounts we can, with the + * exception of the path we want to switch to, plus everything leading to it and within + * it. This is necessary because unlike pivot_root() just moving the mount to the root via + * MS_MOVE won't magically unmount anything below it. Once the chroot() succeeds the mounts + * below would still be around but invisible to us, because not accessible via + * /proc/self/mountinfo. Hence, let's clean everything up first, as long as we still can. */ + (void) umount_recursive_full(NULL, MNT_DETACH, STRV_MAKE(new_root)); + if (mount(".", "/", NULL, MS_MOVE, NULL) < 0) return log_error_errno(errno, "Failed to move %s to /: %m", new_root);