From 430bf378418e655b06d518a7cd62ae680301af80 Mon Sep 17 00:00:00 2001 From: Alistair Strachan Date: Wed, 6 May 2015 15:20:19 -0700 Subject: Fix switch_root implementation. Add the MS_MOVE of cwd to / and chroot into it. chdir is also called to ensure cwd does not point outside the chroot. The switch_root toy was also blocking any case where NEW_ROOT/init did not exist, even though NEW_INIT was a required parameter and did not have to be '/init'. Change it to handle any NEW_INIT passed as either a relative or absolute path. With this change, the switch_root toy actually works from initramfs. --- toys/other/switch_root.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'toys/other/switch_root.c') diff --git a/toys/other/switch_root.c b/toys/other/switch_root.c index 0861c70e..acbae2bb 100644 --- a/toys/other/switch_root.c +++ b/toys/other/switch_root.c @@ -67,8 +67,13 @@ void switch_root_main(void) } TT.rootdev=st2.st_dev; + // trim any / characters from the init cmdline, as we want to test it with + // stat(), relative to newroot. *cmdline is also used below, but by that + // point we are in the chroot, so a relative path is still OK. + while (**cmdline == '/') (*cmdline)++; + // init program must exist and be an executable file - if (stat("init", &st1) || !S_ISREG(st1.st_mode) || !(st1.st_mode&0100)) { + if (stat(*cmdline, &st1) || !S_ISREG(st1.st_mode) || !(st1.st_mode&0100)) { error_msg("bad init"); goto panic; } @@ -81,6 +86,24 @@ void switch_root_main(void) // Ok, enough safety checks: wipe root partition. dirtree_read("/", del_node); + // Fix the appearance of the mount table in the newroot chroot + if (mount(".", "/", NULL, MS_MOVE, NULL)) { + perror_msg("mount"); + goto panic; + } + + // Enter the new root before starting init + if (chroot(".")) { + perror_msg("chroot"); + goto panic; + } + + // Make sure cwd does not point outside of the chroot + if (chdir("/")) { + perror_msg("chdir"); + goto panic; + } + if (TT.console) { int i; for (i=0; i<3; i++) if (console != i) dup2(console, i); -- cgit v1.2.3