init: fix "while true; do reboot; done" bug. +15 bytes. Closes bug 781
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
6be918d0ae
commit
bcc6ec9b7e
115
init/init.c
115
init/init.c
@ -260,6 +260,20 @@ static int open_stdio_to_tty(const char* tty_name)
|
|||||||
return 1; /* success */
|
return 1; /* success */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reset_sighandlers_and_unblock_sigs(void)
|
||||||
|
{
|
||||||
|
bb_signals(0
|
||||||
|
+ (1 << SIGUSR1)
|
||||||
|
+ (1 << SIGUSR2)
|
||||||
|
+ (1 << SIGTERM)
|
||||||
|
+ (1 << SIGQUIT)
|
||||||
|
+ (1 << SIGINT)
|
||||||
|
+ (1 << SIGHUP)
|
||||||
|
+ (1 << SIGTSTP)
|
||||||
|
, SIG_DFL);
|
||||||
|
sigprocmask_allsigs(SIG_UNBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
/* Wrapper around exec:
|
/* Wrapper around exec:
|
||||||
* Takes string (max COMMAND_SIZE chars).
|
* Takes string (max COMMAND_SIZE chars).
|
||||||
* If chars like '>' detected, execs '[-]/bin/sh -c "exec ......."'.
|
* If chars like '>' detected, execs '[-]/bin/sh -c "exec ......."'.
|
||||||
@ -329,16 +343,7 @@ static pid_t run(const struct init_action *a)
|
|||||||
/* Child */
|
/* Child */
|
||||||
|
|
||||||
/* Reset signal handlers that were set by the parent process */
|
/* Reset signal handlers that were set by the parent process */
|
||||||
bb_signals(0
|
reset_sighandlers_and_unblock_sigs();
|
||||||
+ (1 << SIGUSR1)
|
|
||||||
+ (1 << SIGUSR2)
|
|
||||||
+ (1 << SIGTERM)
|
|
||||||
+ (1 << SIGQUIT)
|
|
||||||
+ (1 << SIGINT)
|
|
||||||
+ (1 << SIGHUP)
|
|
||||||
+ (1 << SIGTSTP)
|
|
||||||
, SIG_DFL);
|
|
||||||
sigprocmask_allsigs(SIG_UNBLOCK);
|
|
||||||
|
|
||||||
/* Create a new session and make ourself the process group leader */
|
/* Create a new session and make ourself the process group leader */
|
||||||
setsid();
|
setsid();
|
||||||
@ -651,12 +656,21 @@ static void run_shutdown_and_kill_processes(void)
|
|||||||
* and only one will be remembered and acted upon.
|
* and only one will be remembered and acted upon.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* The SIGUSR[12]/SIGTERM handler */
|
||||||
static void halt_reboot_pwoff(int sig) NORETURN;
|
static void halt_reboot_pwoff(int sig) NORETURN;
|
||||||
static void halt_reboot_pwoff(int sig)
|
static void halt_reboot_pwoff(int sig)
|
||||||
{
|
{
|
||||||
const char *m;
|
const char *m;
|
||||||
unsigned rb;
|
unsigned rb;
|
||||||
|
|
||||||
|
/* We may call run() and it unmasks signals,
|
||||||
|
* including the one masked inside this signal handler.
|
||||||
|
* Testcase which would start multiple reboot scripts:
|
||||||
|
* while true; do reboot; done
|
||||||
|
* Preventing it:
|
||||||
|
*/
|
||||||
|
reset_sighandlers_and_unblock_sigs();
|
||||||
|
|
||||||
run_shutdown_and_kill_processes();
|
run_shutdown_and_kill_processes();
|
||||||
|
|
||||||
m = "halt";
|
m = "halt";
|
||||||
@ -673,6 +687,48 @@ static void halt_reboot_pwoff(int sig)
|
|||||||
/* not reached */
|
/* not reached */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handler for QUIT - exec "restart" action,
|
||||||
|
* else (no such action defined) do nothing */
|
||||||
|
static void restart_handler(int sig UNUSED_PARAM)
|
||||||
|
{
|
||||||
|
struct init_action *a;
|
||||||
|
|
||||||
|
for (a = init_action_list; a; a = a->next) {
|
||||||
|
if (!(a->action_type & RESTART))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Starting from here, we won't return.
|
||||||
|
* Thus don't need to worry about preserving errno
|
||||||
|
* and such.
|
||||||
|
*/
|
||||||
|
|
||||||
|
reset_sighandlers_and_unblock_sigs();
|
||||||
|
|
||||||
|
run_shutdown_and_kill_processes();
|
||||||
|
|
||||||
|
/* Allow Ctrl-Alt-Del to reboot the system.
|
||||||
|
* This is how kernel sets it up for init, we follow suit.
|
||||||
|
*/
|
||||||
|
reboot(RB_ENABLE_CAD); /* misnomer */
|
||||||
|
|
||||||
|
if (open_stdio_to_tty(a->terminal)) {
|
||||||
|
dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command);
|
||||||
|
/* Theoretically should be safe.
|
||||||
|
* But in practice, kernel bugs may leave
|
||||||
|
* unkillable processes, and wait() may block forever.
|
||||||
|
* Oh well. Hoping "new" init won't be too surprised
|
||||||
|
* by having children it didn't create.
|
||||||
|
*/
|
||||||
|
//while (wait(NULL) > 0)
|
||||||
|
// continue;
|
||||||
|
init_exec(a->command);
|
||||||
|
}
|
||||||
|
/* Open or exec failed */
|
||||||
|
pause_and_low_level_reboot(RB_HALT_SYSTEM);
|
||||||
|
/* not reached */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The SIGSTOP/SIGTSTP handler
|
/* The SIGSTOP/SIGTSTP handler
|
||||||
* NB: inside it, all signals except SIGCONT are masked
|
* NB: inside it, all signals except SIGCONT are masked
|
||||||
* via appropriate setup in sigaction().
|
* via appropriate setup in sigaction().
|
||||||
@ -705,45 +761,6 @@ static void stop_handler(int sig UNUSED_PARAM)
|
|||||||
bb_got_signal = saved_bb_got_signal;
|
bb_got_signal = saved_bb_got_signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handler for QUIT - exec "restart" action,
|
|
||||||
* else (no such action defined) do nothing */
|
|
||||||
static void restart_handler(int sig UNUSED_PARAM)
|
|
||||||
{
|
|
||||||
struct init_action *a;
|
|
||||||
|
|
||||||
for (a = init_action_list; a; a = a->next) {
|
|
||||||
if (!(a->action_type & RESTART))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Starting from here, we won't return.
|
|
||||||
* Thus don't need to worry about preserving errno
|
|
||||||
* and such.
|
|
||||||
*/
|
|
||||||
run_shutdown_and_kill_processes();
|
|
||||||
|
|
||||||
/* Allow Ctrl-Alt-Del to reboot the system.
|
|
||||||
* This is how kernel sets it up for init, we follow suit.
|
|
||||||
*/
|
|
||||||
reboot(RB_ENABLE_CAD); /* misnomer */
|
|
||||||
|
|
||||||
if (open_stdio_to_tty(a->terminal)) {
|
|
||||||
dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command);
|
|
||||||
/* Theoretically should be safe.
|
|
||||||
* But in practice, kernel bugs may leave
|
|
||||||
* unkillable processes, and wait() may block forever.
|
|
||||||
* Oh well. Hoping "new" init won't be too surprised
|
|
||||||
* by having children it didn't create.
|
|
||||||
*/
|
|
||||||
//while (wait(NULL) > 0)
|
|
||||||
// continue;
|
|
||||||
init_exec(a->command);
|
|
||||||
}
|
|
||||||
/* Open or exec failed */
|
|
||||||
pause_and_low_level_reboot(RB_HALT_SYSTEM);
|
|
||||||
/* not reached */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_USE_INITTAB
|
#if ENABLE_FEATURE_USE_INITTAB
|
||||||
static void reload_inittab(void)
|
static void reload_inittab(void)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user