init: do not run shutdown/reexec actions from signal handler
this is racy wrt various libc functions such as syslog() function old new delta check_delayed_sigs 182 352 +170 init_main 772 728 -44 restart_handler 74 - -74 halt_reboot_pwoff 79 - -79 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 1/1 up/down: 170/-197) Total: -27 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
4e314faa0a
commit
2bba9ad67a
50
init/init.c
50
init/init.c
@ -822,7 +822,7 @@ static void halt_reboot_pwoff(int sig)
|
|||||||
|
|
||||||
/* Handler for QUIT - exec "restart" action,
|
/* Handler for QUIT - exec "restart" action,
|
||||||
* else (no such action defined) do nothing */
|
* else (no such action defined) do nothing */
|
||||||
static void restart_handler(int sig UNUSED_PARAM)
|
static void exec_restart_action(void)
|
||||||
{
|
{
|
||||||
struct init_action *a;
|
struct init_action *a;
|
||||||
|
|
||||||
@ -975,6 +975,20 @@ static int check_delayed_sigs(void)
|
|||||||
#endif
|
#endif
|
||||||
if (sig == SIGINT)
|
if (sig == SIGINT)
|
||||||
run_actions(CTRLALTDEL);
|
run_actions(CTRLALTDEL);
|
||||||
|
if (sig == SIGQUIT) {
|
||||||
|
exec_restart_action();
|
||||||
|
/* returns only if no restart action defined */
|
||||||
|
}
|
||||||
|
if ((1 << sig) & (0
|
||||||
|
#ifdef SIGPWR
|
||||||
|
+ (1 << SIGPWR)
|
||||||
|
#endif
|
||||||
|
+ (1 << SIGUSR1)
|
||||||
|
+ (1 << SIGUSR2)
|
||||||
|
+ (1 << SIGTERM)
|
||||||
|
)) {
|
||||||
|
halt_reboot_pwoff(sig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,7 +1084,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* It's 2013, does anyone really still depend on this? */
|
/* It's 2013, does anyone really still depend on this? */
|
||||||
/* If you do, consider adding swapon to sysinot actions then! */
|
/* If you do, consider adding swapon to sysinit actions then! */
|
||||||
/* struct sysinfo is linux-specific */
|
/* struct sysinfo is linux-specific */
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
/* Make sure there is enough memory to do something useful. */
|
/* Make sure there is enough memory to do something useful. */
|
||||||
@ -1134,16 +1148,6 @@ int init_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (!DEBUG_INIT) {
|
if (!DEBUG_INIT) {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
bb_signals(0
|
|
||||||
#ifdef SIGPWR
|
|
||||||
+ (1 << SIGPWR) /* halt */
|
|
||||||
#endif
|
|
||||||
+ (1 << SIGUSR1) /* halt */
|
|
||||||
+ (1 << SIGTERM) /* reboot */
|
|
||||||
+ (1 << SIGUSR2) /* poweroff */
|
|
||||||
, halt_reboot_pwoff);
|
|
||||||
signal(SIGQUIT, restart_handler); /* re-exec another init */
|
|
||||||
|
|
||||||
/* Stop handler must allow only SIGCONT inside itself */
|
/* Stop handler must allow only SIGCONT inside itself */
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sigfillset(&sa.sa_mask);
|
sigfillset(&sa.sa_mask);
|
||||||
@ -1158,18 +1162,24 @@ int init_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
*/
|
*/
|
||||||
sigaction_set(SIGSTOP, &sa); /* pause */
|
sigaction_set(SIGSTOP, &sa); /* pause */
|
||||||
|
|
||||||
/* SIGINT (Ctrl-Alt-Del) must interrupt wait(),
|
/* These signals must interrupt wait(),
|
||||||
* setting handler without SA_RESTART flag.
|
* setting handler without SA_RESTART flag.
|
||||||
*/
|
*/
|
||||||
bb_signals_recursive_norestart((1 << SIGINT), record_signo);
|
bb_signals_recursive_norestart(0
|
||||||
|
+ (1 << SIGINT) /* Ctrl-Alt-Del */
|
||||||
|
+ (1 << SIGQUIT) /* re-exec another init */
|
||||||
|
#ifdef SIGPWR
|
||||||
|
+ (1 << SIGPWR) /* halt */
|
||||||
|
#endif
|
||||||
|
+ (1 << SIGUSR1) /* halt */
|
||||||
|
+ (1 << SIGTERM) /* reboot */
|
||||||
|
+ (1 << SIGUSR2) /* poweroff */
|
||||||
|
#if ENABLE_FEATURE_USE_INITTAB
|
||||||
|
+ (1 << SIGHUP) /* reread /etc/inittab */
|
||||||
|
#endif
|
||||||
|
, record_signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up "reread /etc/inittab" handler.
|
|
||||||
* Handler is set up without SA_RESTART, it will interrupt syscalls.
|
|
||||||
*/
|
|
||||||
if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB)
|
|
||||||
bb_signals_recursive_norestart((1 << SIGHUP), record_signo);
|
|
||||||
|
|
||||||
/* Now run everything that needs to be run */
|
/* Now run everything that needs to be run */
|
||||||
/* First run the sysinit command */
|
/* First run the sysinit command */
|
||||||
run_actions(SYSINIT);
|
run_actions(SYSINIT);
|
||||||
|
Loading…
Reference in New Issue
Block a user