From 335fe94f907864b647160ab616d8caa91a983287 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Tue, 14 Aug 2018 11:01:52 +0000 Subject: [PATCH] Add init_exec kenv(1) variable, to make init(8) execute a file after opening the console, replacing init as PID 1. From the user point of view, it makes it possible to run eg the shell as PID 1, using 'set init_exec=/bin/sh' at the loader(8) prompt. Reviewed by: kib MFC after: 2 weeks Relnotes: yes Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D16625 --- sbin/init/init.8 | 12 +++++++++++- sbin/init/init.c | 22 ++++++++++++++++++++++ stand/man/loader.8 | 5 ++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/sbin/init/init.8 b/sbin/init/init.8 index 89a94a38b448..28580f42f077 100644 --- a/sbin/init/init.8 +++ b/sbin/init/init.8 @@ -31,7 +31,7 @@ .\" @(#)init.8 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd August 7, 2018 +.Dd August 14, 2018 .Dt INIT 8 .Os .Sh NAME @@ -316,6 +316,14 @@ See .Xr reboot 8 .Fl r for details. +.It Va init_exec +If set to a valid file name in the root file system, +instructs +.Nm +to directly execute that file as the very first action, +replacing +.Nm +as PID 1. .It Va init_script If set to a valid file name in the root file system, instructs @@ -341,6 +349,8 @@ Defines the shell binary to be used for executing the various shell scripts. The default is .Dq Li /bin/sh . It is used for running the +.Va init_exec +or .Va init_script if set, as well as for the .Pa /etc/rc diff --git a/sbin/init/init.c b/sbin/init/init.c index feda5a3c0bae..c06aff539f32 100644 --- a/sbin/init/init.c +++ b/sbin/init/init.c @@ -149,6 +149,7 @@ static state_t current_state = death_single; static void execute_script(char *argv[]); static void open_console(void); static const char *get_shell(void); +static void replace_init(char *path); static void write_stderr(const char *message); typedef struct init_session { @@ -330,6 +331,11 @@ main(int argc, char *argv[]) close(1); close(2); + if (kenv(KENV_GET, "init_exec", kenv_value, sizeof(kenv_value)) > 0) { + replace_init(kenv_value); + _exit(0); /* reboot */ + } + if (kenv(KENV_GET, "init_script", kenv_value, sizeof(kenv_value)) > 0) { state_func_t next_transition; @@ -1087,6 +1093,22 @@ execute_script(char *argv[]) stall("can't exec %s for %s: %m", shell, script); } +/* + * Execute binary, replacing init(8) as PID 1. + */ +static void +replace_init(char *path) +{ + char *argv[3]; + char sh[] = "sh"; + + argv[0] = sh; + argv[1] = path; + argv[2] = NULL; + + execute_script(argv); +} + /* * Run a shell script. * Returns 0 on success, otherwise the next transition to enter: diff --git a/stand/man/loader.8 b/stand/man/loader.8 index 0b9a2a2fe1d7..374b6ee0d9d6 100644 --- a/stand/man/loader.8 +++ b/stand/man/loader.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 13, 2018 +.Dd August 14, 2018 .Dt LOADER 8 .Os .Sh NAME @@ -492,6 +492,9 @@ of boot to be captured. .It Va init_chroot See .Xr init 8 . +.It Va init_exec +See +.Xr init 8 . .It Va init_path Sets the list of binaries which the kernel will try to run as the initial process.