summaryrefslogtreecommitdiffstats
path: root/sys-utils/switch_root.c
diff options
context:
space:
mode:
authorHarald Hoyer2011-10-20 10:05:20 +0200
committerKarel Zak2011-10-20 12:27:35 +0200
commitacb03ad46a0f5160fe7a1c9d9ec09c35494d3051 (patch)
treec2e770cf10e8a1d10ddbafa33d4e88ca3e4ada88 /sys-utils/switch_root.c
parentmount: remounting tmpfs read-write hangs (selinux) (diff)
downloadkernel-qcow2-util-linux-acb03ad46a0f5160fe7a1c9d9ec09c35494d3051.tar.gz
kernel-qcow2-util-linux-acb03ad46a0f5160fe7a1c9d9ec09c35494d3051.tar.xz
kernel-qcow2-util-linux-acb03ad46a0f5160fe7a1c9d9ec09c35494d3051.zip
switch_root: handle /run and do not mount over existing mounts
Handle /run just like /dev, /sys and /proc Do not mount move, if there is already something mounted on the destination folder. Signed-off-by: Harald Hoyer <harald@redhat.com> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/switch_root.c')
-rw-r--r--sys-utils/switch_root.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/sys-utils/switch_root.c b/sys-utils/switch_root.c
index 2dfed71a0..f86b8c697 100644
--- a/sys-utils/switch_root.c
+++ b/sys-utils/switch_root.c
@@ -111,16 +111,28 @@ done:
static int switchroot(const char *newroot)
{
/* Don't try to unmount the old "/", there's no way to do it. */
- const char *umounts[] = { "/dev", "/proc", "/sys", NULL };
+ const char *umounts[] = { "/dev", "/proc", "/sys", "/run", NULL };
int i;
int cfd;
pid_t pid;
+ struct stat newroot_stat, sb;
+
+ if (stat(newroot, &newroot_stat) != 0) {
+ warn("failed to stat directory %s", newroot);
+ return -1;
+ }
for (i = 0; umounts[i] != NULL; i++) {
char newmount[PATH_MAX];
snprintf(newmount, sizeof(newmount), "%s%s", newroot, umounts[i]);
+ if ((stat(newmount, &sb) != 0) || (sb.st_dev != newroot_stat.st_dev)) {
+ /* mount point seems to be mounted already or stat failed */
+ umount(umounts[i]);
+ continue;
+ }
+
if (mount(umounts[i], newmount, NULL, MS_MOVE, NULL) < 0) {
warn("failed to mount moving %s to %s",
umounts[i], newmount);