run-init: implement -n "dry run"
function old new delta switch_root_main 637 706 +69 packed_usage 31743 31757 +14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 83/0) Total: 83 bytes text data bss dec hex filename 915247 563 5844 921654 e1036 busybox_old 915303 563 5844 921710 e106e busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
200bcc851a
commit
bbc26c6934
@ -679,7 +679,7 @@ int setfiles_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
bb_show_usage();
|
bb_show_usage();
|
||||||
xstat(argv[0], &sb);
|
xstat(argv[0], &sb);
|
||||||
if (!S_ISREG(sb.st_mode)) {
|
if (!S_ISREG(sb.st_mode)) {
|
||||||
bb_error_msg_and_die("spec file %s is not a regular file", argv[0]);
|
bb_error_msg_and_die("'%s' is not a regular file", argv[0]);
|
||||||
}
|
}
|
||||||
/* Load the file contexts configuration and check it. */
|
/* Load the file contexts configuration and check it. */
|
||||||
rc = matchpathcon_init(argv[0]);
|
rc = matchpathcon_init(argv[0]);
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
//config: * Because the Linux kernel uses rootfs internally as the starting
|
//config: * Because the Linux kernel uses rootfs internally as the starting
|
||||||
//config: and ending point for searching through the kernel's doubly linked
|
//config: and ending point for searching through the kernel's doubly linked
|
||||||
//config: list of active mount points. That's why.
|
//config: list of active mount points. That's why.
|
||||||
|
//config:
|
||||||
|
// RUN_INIT config item is in klibc-utils
|
||||||
|
|
||||||
//applet:IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP))
|
//applet:IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP))
|
||||||
// APPLET_ODDNAME:name main location suid_type help
|
// APPLET_ODDNAME:name main location suid_type help
|
||||||
@ -32,23 +34,6 @@
|
|||||||
//kbuild:lib-$(CONFIG_SWITCH_ROOT) += switch_root.o
|
//kbuild:lib-$(CONFIG_SWITCH_ROOT) += switch_root.o
|
||||||
//kbuild:lib-$(CONFIG_RUN_INIT) += switch_root.o
|
//kbuild:lib-$(CONFIG_RUN_INIT) += switch_root.o
|
||||||
|
|
||||||
//usage:#define switch_root_trivial_usage
|
|
||||||
//usage: "[-c CONSOLE_DEV] NEW_ROOT NEW_INIT [ARGS]"
|
|
||||||
//usage:#define switch_root_full_usage "\n\n"
|
|
||||||
//usage: "Free initramfs and switch to another root fs:\n"
|
|
||||||
//usage: "chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,\n"
|
|
||||||
//usage: "execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.\n"
|
|
||||||
//usage: "\n -c DEV Reopen stdio to DEV after switch"
|
|
||||||
|
|
||||||
//usage:#define run_init_trivial_usage
|
|
||||||
//usage: "[-d CAP,CAP...] [-c CONSOLE_DEV] NEW_ROOT NEW_INIT [ARGS]"
|
|
||||||
//usage:#define run_init_full_usage "\n\n"
|
|
||||||
//usage: "Free initramfs and switch to another root fs:\n"
|
|
||||||
//usage: "chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,\n"
|
|
||||||
//usage: "execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.\n"
|
|
||||||
//usage: "\n -c DEV Reopen stdio to DEV after switch"
|
|
||||||
//usage: "\n -d CAPS Drop capabilities"
|
|
||||||
|
|
||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#if ENABLE_RUN_INIT
|
#if ENABLE_RUN_INIT
|
||||||
@ -122,13 +107,8 @@ static void drop_capset(int cap_idx)
|
|||||||
{
|
{
|
||||||
struct caps caps;
|
struct caps caps;
|
||||||
|
|
||||||
/* Get the current capability mask */
|
|
||||||
getcaps(&caps);
|
getcaps(&caps);
|
||||||
|
|
||||||
/* Drop the bit */
|
|
||||||
caps.data[CAP_TO_INDEX(cap_idx)].inheritable &= ~CAP_TO_MASK(cap_idx);
|
caps.data[CAP_TO_INDEX(cap_idx)].inheritable &= ~CAP_TO_MASK(cap_idx);
|
||||||
|
|
||||||
/* And drop the capability. */
|
|
||||||
if (capset(&caps.header, caps.data) != 0)
|
if (capset(&caps.header, caps.data) != 0)
|
||||||
bb_perror_msg_and_die("capset");
|
bb_perror_msg_and_die("capset");
|
||||||
}
|
}
|
||||||
@ -199,10 +179,18 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
char *newroot, *console = NULL;
|
char *newroot, *console = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct statfs stfs;
|
struct statfs stfs;
|
||||||
|
unsigned dry_run = 0;
|
||||||
dev_t rootdev;
|
dev_t rootdev;
|
||||||
|
|
||||||
// Parse args (-c console). '+': stop at first non-option
|
// Parse args. '+': stop at first non-option
|
||||||
if (ENABLE_SWITCH_ROOT && (!ENABLE_RUN_INIT || applet_name[0] == 's')) {
|
if (ENABLE_SWITCH_ROOT && (!ENABLE_RUN_INIT || applet_name[0] == 's')) {
|
||||||
|
//usage:#define switch_root_trivial_usage
|
||||||
|
//usage: "[-c CONSOLE_DEV] NEW_ROOT NEW_INIT [ARGS]"
|
||||||
|
//usage:#define switch_root_full_usage "\n\n"
|
||||||
|
//usage: "Free initramfs and switch to another root fs:\n"
|
||||||
|
//usage: "chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,\n"
|
||||||
|
//usage: "execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.\n"
|
||||||
|
//usage: "\n -c DEV Reopen stdio to DEV after switch"
|
||||||
getopt32(argv, "^+"
|
getopt32(argv, "^+"
|
||||||
"c:"
|
"c:"
|
||||||
"\0" "-2" /* minimum 2 args */,
|
"\0" "-2" /* minimum 2 args */,
|
||||||
@ -210,13 +198,23 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
#if ENABLE_RUN_INIT
|
#if ENABLE_RUN_INIT
|
||||||
|
//usage:#define run_init_trivial_usage
|
||||||
|
//usage: "[-d CAP,CAP...] [-n] [-c CONSOLE_DEV] NEW_ROOT NEW_INIT [ARGS]"
|
||||||
|
//usage:#define run_init_full_usage "\n\n"
|
||||||
|
//usage: "Free initramfs and switch to another root fs:\n"
|
||||||
|
//usage: "chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,\n"
|
||||||
|
//usage: "execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.\n"
|
||||||
|
//usage: "\n -c DEV Reopen stdio to DEV after switch"
|
||||||
|
//usage: "\n -d CAPS Drop capabilities"
|
||||||
|
//usage: "\n -n Dry run"
|
||||||
char *cap_list = NULL;
|
char *cap_list = NULL;
|
||||||
getopt32(argv, "^+"
|
dry_run = getopt32(argv, "^+"
|
||||||
"c:d:"
|
"c:d:n"
|
||||||
"\0" "-2" /* minimum 2 args */,
|
"\0" "-2" /* minimum 2 args */,
|
||||||
&console,
|
&console,
|
||||||
&cap_list
|
&cap_list
|
||||||
);
|
);
|
||||||
|
dry_run >>= 2; // -n
|
||||||
if (cap_list)
|
if (cap_list)
|
||||||
drop_capabilities(cap_list);
|
drop_capabilities(cap_list);
|
||||||
#endif
|
#endif
|
||||||
@ -239,7 +237,7 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
// we mean it. I could make this a CONFIG option, but I would get email
|
// we mean it. I could make this a CONFIG option, but I would get email
|
||||||
// from all the people who WILL destroy their filesystems.
|
// from all the people who WILL destroy their filesystems.
|
||||||
if (stat("/init", &st) != 0 || !S_ISREG(st.st_mode)) {
|
if (stat("/init", &st) != 0 || !S_ISREG(st.st_mode)) {
|
||||||
bb_error_msg_and_die("/init is not a regular file");
|
bb_error_msg_and_die("'%s' is not a regular file", "/init");
|
||||||
}
|
}
|
||||||
statfs("/", &stfs); // this never fails
|
statfs("/", &stfs); // this never fails
|
||||||
if ((unsigned)stfs.f_type != RAMFS_MAGIC
|
if ((unsigned)stfs.f_type != RAMFS_MAGIC
|
||||||
@ -248,13 +246,15 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
bb_error_msg_and_die("root filesystem is not ramfs/tmpfs");
|
bb_error_msg_and_die("root filesystem is not ramfs/tmpfs");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zap everything out of rootdev
|
if (!dry_run) {
|
||||||
delete_contents("/", rootdev);
|
// Zap everything out of rootdev
|
||||||
|
delete_contents("/", rootdev);
|
||||||
|
|
||||||
// Overmount / with newdir and chroot into it
|
// Overmount / with newdir and chroot into it
|
||||||
if (mount(".", "/", NULL, MS_MOVE, NULL)) {
|
if (mount(".", "/", NULL, MS_MOVE, NULL)) {
|
||||||
// For example, fails when newroot is not a mountpoint
|
// For example, fails when newroot is not a mountpoint
|
||||||
bb_perror_msg_and_die("error moving root");
|
bb_perror_msg_and_die("error moving root");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xchroot(".");
|
xchroot(".");
|
||||||
// The chdir is needed to recalculate "." and ".." links
|
// The chdir is needed to recalculate "." and ".." links
|
||||||
@ -270,8 +270,17 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec real init
|
if (dry_run) {
|
||||||
execv(argv[0], argv);
|
// Does NEW_INIT look like it can be executed?
|
||||||
|
//xstat(argv[0], &st);
|
||||||
|
//if (!S_ISREG(st.st_mode))
|
||||||
|
// bb_perror_msg_and_die("'%s' is not a regular file", argv[0]);
|
||||||
|
if (access(argv[0], X_OK) == 0)
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
// Exec NEW_INIT
|
||||||
|
execv(argv[0], argv);
|
||||||
|
}
|
||||||
bb_perror_msg_and_die("can't execute '%s'", argv[0]);
|
bb_perror_msg_and_die("can't execute '%s'", argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user