This reverts commit a692a8745941a192528c5e2a05de97155ba586f9. Booting into a system this way just leads to problems because you cannot remount the root read-only at shutdown (leading to unclean shutdowns). Miklos Szeredi pointed out a trick to turn any directory into a mount point which avoids this problem. Therefore we can simplify switch_root again and simply document that its users should set up the root as a mount point beforehand. --- sys-utils/switch_root.8 | 13 +++++++ sys-utils/switch_root.c | 81 +++-------------------------------------------- 2 files changed, 18 insertions(+), 76 deletions(-) diff --git a/sys-utils/switch_root.8 b/sys-utils/switch_root.8 index 4fdc8e9..b6712ec 100644 --- a/sys-utils/switch_root.8 +++ b/sys-utils/switch_root.8 @@ -32,6 +32,19 @@ show version number and exit .B switch_root returns 0 on success and 1 on failure. +.SH NOTES +switch_root will fail to function if +.B newroot +is not the root of a mount. If you want to switch root into a directory that +does not meet this requirement then you can first use a bind-mounting trick to +turn any directory into a mount point: +.sp +.nf +.RS +mount --bind $DIR $DIR +.RE +.fi + .SH "SEE ALSO" .BR mount (8) .BR chroot (2) diff --git a/sys-utils/switch_root.c b/sys-utils/switch_root.c index 174e667..c43225d 100644 --- a/sys-utils/switch_root.c +++ b/sys-utils/switch_root.c @@ -33,7 +33,6 @@ #include <ctype.h> #include <dirent.h> #include <err.h> -#include <libgen.h> #ifndef MS_MOVE #define MS_MOVE 8192 @@ -109,58 +108,13 @@ done: return rc; } -/* find the enclosing mount point of a path, by examining the backing device - * of parent directories until we reach / or find a parent with a differing - * device. Result must be freed. - */ -static char *get_parent_mount(const char *path) -{ - struct stat sb; - char *dir; - char tmp[PATH_MAX]; - dev_t inner_dev; - - if (stat(path, &sb) != 0) { - warn("failed to stat %s", path); - return NULL; - } - - inner_dev = sb.st_dev; - dir = strdup(path); - - while (dir) { - char *parent; - - strncpy(tmp, dir, PATH_MAX); - tmp[PATH_MAX - 1] = '\0'; - parent = dirname(tmp); - - if (stat(parent, &sb) != 0) { - warn("failed to stat %s", parent); - return NULL; - } - if (sb.st_dev != inner_dev) - return dir; - - strncpy(dir, parent, PATH_MAX); - dir[PATH_MAX - 1] = '\0'; - - /* maybe we've reached / */ - if (*dir == '/' && !*(dir + 1)) - return dir; - } - return NULL; -} - 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 }; int i; - int cfd, rc = -1; + int cfd; pid_t pid; - const char *chroot_path = NULL; - char *newroot_mnt; for (i = 0; umounts[i] != NULL; i++) { char newmount[PATH_MAX]; @@ -175,43 +129,21 @@ static int switchroot(const char *newroot) } } - newroot_mnt = get_parent_mount(newroot); - if (newroot_mnt && strcmp(newroot, newroot_mnt)) { - /* newroot is not a mount point, so we have to MS_MOVE the - * parent mount point and then chroot in to the "subroot" - */ - chroot_path = newroot + strlen(newroot_mnt); - newroot = newroot_mnt; - } - if (chdir(newroot)) { warn("failed to change directory to %s", newroot); - goto done; + return -1; } cfd = open("/", O_RDONLY); if (mount(newroot, "/", NULL, MS_MOVE, NULL) < 0) { warn("failed to mount moving %s to /", newroot); - goto done; + return -1; } - /* move to the real root of the device */ if (chroot(".")) { warn("failed to change root"); - goto done; - } - - /* move to the subdirectory on the root device (subroot) */ - if (chroot_path) { - if (chdir(chroot_path)) { - warn("failed to chdir to subroot %s", chroot_path); - goto done; - } - if (chroot(".")) { - warn("failed to change root to subroot %s", chroot_path); - goto done; - } + return -1; } if (cfd >= 0) { @@ -223,10 +155,7 @@ static int switchroot(const char *newroot) } close(cfd); } - rc = 0; -done: - free(newroot_mnt); - return rc; + return 0; } static void usage(FILE *output) -- 1.6.2.5 -- To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html