diff options
author | Alistair Strachan <alistair.strachan@imgtec.com> | 2015-05-06 15:20:19 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2015-08-08 16:57:30 -0500 |
commit | 430bf378418e655b06d518a7cd62ae680301af80 (patch) | |
tree | ad5a0364976f57f7210d59f73f0f5b8eb9084b25 | |
parent | 5fb2766a9b51ee326a14ec9909066b20a2bfa9ac (diff) | |
download | toybox-430bf378418e655b06d518a7cd62ae680301af80.tar.gz |
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.
-rw-r--r-- | toys/other/switch_root.c | 25 |
1 files changed, 24 insertions, 1 deletions
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); |