From 268d1244e87a35ff8dff56c92ef375ebf69d462e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 May 2023 21:25:12 +0200 Subject: [PATCH] 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. --- src/shared/switch-root.c | 8 ++++++++ 1 file changed, 8 insertions(+) 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); -- 2.47.3