diff options
author | H. Peter Anvin <hpa@zytor.com> | 2004-06-08 19:28:08 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2004-06-08 19:28:08 +0000 |
commit | cc0c0262446a10f69c10d5ddac3dd6536f2f9917 (patch) | |
tree | 7e8fcff9f9c3e9d4eb34d7d691c8d1b99bb10c14 | |
parent | 34ebe698f9c52ca01bbe5ad5cea6fd4af591bb93 (diff) | |
download | klibc-cc0c0262446a10f69c10d5ddac3dd6536f2f9917.tar.gz |
Add more checks, add handling of consoleklibc-0.130
-rw-r--r-- | utils/run-init.c | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/utils/run-init.c b/utils/run-init.c index 5e95962a0ac32..8ac953bcf46c6 100644 --- a/utils/run-init.c +++ b/utils/run-init.c @@ -1,4 +1,4 @@ -#ident "$Id: run-init.c,v 1.2 2004/06/08 06:40:33 hpa Exp $" +#ident "$Id: run-init.c,v 1.3 2004/06/08 20:24:42 hpa Exp $" /* ----------------------------------------------------------------------- * * * Copyright 2004 H. Peter Anvin - All Rights Reserved @@ -29,7 +29,7 @@ /* * run-init.c * - * Usage: exec run-init /real-root /sbin/init "$@" + * Usage: exec run-init [-c /dev/console] /real-root /sbin/init "$@" * * This program should be called as the last thing in a shell script * acting as /init in an initramfs; it does the following: @@ -37,6 +37,7 @@ * - Delete all files in the initramfs; * - Remounts /real-root onto the root filesystem; * - Chroots; + * - Opens /dev/console; * - Spawns the specified init program (with arguments.) */ @@ -44,6 +45,7 @@ #include <assert.h> #include <dirent.h> #include <errno.h> +#include <fcntl.h> #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -146,42 +148,93 @@ static int nuke(const char *what) } } + +static void __attribute__((noreturn)) usage(void) +{ + fprintf(stderr, "Usage: exec %s [-c consoledev] /real-root /sbin/init [args]\n", program); + exit(1); +} + + int main(int argc, char *argv[]) { + struct stat rst, cst, ist; struct statfs sfs; + int o; + int confd; + /* Command-line options and defaults */ + const char *console = "/dev/console"; + const char *realroot; + const char *init; + char **initargs; + + /* First, parse the command line */ program = argv[0]; - if ( argc < 3 ) { - fprintf(stderr, "Usage: exec %s /real-root /sbin/init [args]\n", program); - exit(1); + while ( (o = getopt(argc, argv, "c:")) != -1 ) { + if ( o == 'c' ) { + console = optarg; + } else { + usage(); + } } - /* Make sure we're in the root directory */ - if ( chdir("/") ) - die("cd /"); - - /* Make sure we're on a ramfs - this avoids accidents */ - if ( statfs(".", &sfs) ) + if ( argc-optind < 2 ) + usage(); + + realroot = argv[optind]; + init = argv[optind+1]; + initargs = argv+optind+1; + + /* First, change to the new root directory */ + if ( chdir(argv[1]) ) + die("chdir to new root"); + + /* This is a potentially highly destructive program. Take some + extra precautions. */ + + /* Make sure the current directory is not on the same filesystem + as the root directory */ + if ( stat("/", &rst) || stat(".", &cst) ) + die("stat"); + + if ( rst.st_dev == cst.st_dev ) + die("current directory on the same filesystem as the root"); + + /* The initramfs should have /init */ + if ( stat("/init", &ist) || !S_ISREG(ist.st_mode) ) + die("can't find /init on initramfs"); + + /* Make sure we're on a ramfs */ + if ( statfs("/", &sfs) ) die("statfs /"); if ( sfs.f_type != RAMFS_MAGIC && sfs.f_type != TMPFS_MAGIC ) die("rootfs not a ramfs or tmpfs"); + /* Okay, I think we should be safe... */ + /* Delete rootfs contents */ - if ( nuke_dir(".") ) + if ( nuke_dir("/") ) die("nuking initramfs contents"); /* Overmount the root */ - if ( mount(argv[2], "/", NULL, MS_BIND, NULL) ) + if ( mount(".", "/", NULL, MS_BIND, NULL) ) die("overmounting root"); - /* Chroot */ - if ( chroot(".") ) + /* chroot, chdir */ + if ( chroot(".") || chdir("/") ) die("chroot"); - /* Spawn init */ - execv(argv[3], argv+3); + /* Open /dev/console */ + if ( (confd = open(console, O_RDWR)) < 0 ) + die("opening console"); + dup2(confd, 0); + dup2(confd, 1); + dup2(confd, 2); + close(confd); - die(argv[3]); /* Failed to spawn init */ + /* Spawn init */ + execv(init, initargs); + die(init); /* Failed to spawn init */ } - |