diff options
Diffstat (limited to 'init/init.c')
-rw-r--r-- | init/init.c | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/init/init.c b/init/init.c index 913436353..b0a85829d 100644 --- a/init/init.c +++ b/init/init.c @@ -147,7 +147,9 @@ void message(int device, char *fmt, ...) va_start(arguments, fmt); vsnprintf(msg, sizeof(msg), fmt, arguments); va_end(arguments); + openlog( "init", 0, LOG_DAEMON); syslog(LOG_DAEMON|LOG_NOTICE, msg); + closelog(); } #else @@ -268,7 +270,7 @@ static void console_init() #if #cpu(sparc) /* sparc kernel supports console=tty[ab] parameter which is also * passed to init, so catch it here */ - else if ((s = getenv("console")) != NULL) {*/ + else if ((s = getenv("console")) != NULL) { /* remap tty[ab] to /dev/ttyS[01] */ if (strcmp( s, "ttya" )==0) snprintf(console, sizeof(console)-1, "%s", SERIAL_CON0); @@ -507,7 +509,83 @@ static void reboot_signal(int sig) exit(0); } -#endif +#if defined BB_FEATURE_INIT_CHROOT +static void check_chroot(int sig) +{ + char *argv_init[2] = { "init", NULL, }; + char *envp_init[3] = { "HOME=/", "TERM=linux", NULL, }; + char rootpath[256], *tc; + int fd; + + if ((fd = open("/proc/sys/kernel/init-chroot", O_RDONLY)) == -1) { + message(CONSOLE, "SIGHUP recived, but could not open proc file\r\n"); + sleep(2); + return; + } + if (read(fd, rootpath, sizeof(rootpath)) == -1) { + message(CONSOLE, "SIGHUP recived, but could not read proc file\r\n"); + sleep(2); + return; + } + close(fd); + + if (rootpath[0] == '\0') { + message(CONSOLE, "SIGHUP recived, but new root is not valid: %s\r\n", + rootpath); + sleep(2); + return; + } + + tc = strrchr(rootpath, '\n'); + *tc = '\0'; + + /* Ok, making it this far means we commit */ + message(CONSOLE, "Please stand by, changing root to `%s'.\r\n", rootpath); + + /* kill all other programs first */ + message(CONSOLE, "Sending SIGTERM to all processes.\r\n"); + kill(-1, SIGTERM); + sleep(2); + sync(); + + message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); + kill(-1, SIGKILL); + sleep(2); + sync(); + + /* ok, we don't need /proc anymore. we also assume that the signaling + * process left the rest of the filesystems alone for us */ + umount("/proc"); + + /* Ok, now we chroot. Hopefully we only have two things mounted, the + * new chroot'd mount point, and the old "/" mount. s, + * we go ahead and unmount the old "/". This should trigger the kernel + * to set things up the Right Way(tm). */ + + if (!chroot(rootpath)) + umount("/dev/root"); + + /* If the chroot fails, we are already too far to turn back, so we + * continue and hope that executing init below will revive the system */ + + /* close all of our descriptors and open new ones */ + close(0); + close(1); + close(2); + open("/dev/console", O_RDWR, 0); + dup(0); + dup(0); + + message(CONSOLE, "Executing real init...\r\n"); + /* execute init in the (hopefully) new root */ + execve("/sbin/init",argv_init,envp_init); + + message(CONSOLE, "ERROR: Could not exec new init. Hit ctrl+alt+delete to reboot.\r\n"); + return; +} +#endif /* BB_FEATURE_INIT_CHROOT */ + +#endif /* ! DEBUG_INIT */ void new_initAction (initActionEnum action, char* process, char* cons) @@ -516,10 +594,10 @@ void new_initAction (initActionEnum action, /* If BusyBox detects that a serial console is in use, * then entries containing non-empty id fields will _not_ be run. + * The exception to this rule is the null device. */ - if (secondConsole == NULL && *cons != '\0') { + if (secondConsole == NULL && (*cons != '\0' || strncmp(cons, "null", 4))) return; - } newAction = calloc ((size_t)(1), sizeof(initAction)); if (!newAction) { @@ -662,7 +740,7 @@ extern int init_main(int argc, char **argv) int status; #ifndef DEBUG_INIT - /* Expect to be PID 1 iff we are run as init (not linuxrc) */ + /* Expect to be PID 1 if we are run as init (not linuxrc) */ if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) { usage( "init\n\nInit is the parent of all processes.\n\n" "This version of init is designed to be run only by the kernel\n"); @@ -676,6 +754,9 @@ extern int init_main(int argc, char **argv) signal(SIGUSR2, reboot_signal); signal(SIGINT, reboot_signal); signal(SIGTERM, reboot_signal); +#if defined BB_FEATURE_INIT_CHROOT + signal(SIGHUP, check_chroot); +#endif /* Turn off rebooting via CTL-ALT-DEL -- we get a * SIGINT on CAD so we can shut things down gracefully... */ |