diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2014-11-21 20:10:57 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2014-11-21 20:10:57 +0100 |
commit | 2bba9ad67a917de2624d427c8c107ce3e2d3d085 (patch) | |
tree | 9557d8e5b55ed51cee72561c53bb712e23785511 | |
parent | 4e314faa0aecb66717418e9a47a4451aec59262b (diff) | |
download | busybox-2bba9ad67a917de2624d427c8c107ce3e2d3d085.tar.gz |
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>
-rw-r--r-- | init/init.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/init/init.c b/init/init.c index de438be20..d99d68ce4 100644 --- a/init/init.c +++ b/init/init.c @@ -822,7 +822,7 @@ static void halt_reboot_pwoff(int sig) /* Handler for QUIT - exec "restart" action, * 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; @@ -975,6 +975,20 @@ static int check_delayed_sigs(void) #endif if (sig == SIGINT) 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 /* 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 */ # ifdef __linux__ /* 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) { 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 */ memset(&sa, 0, sizeof(sa)); sigfillset(&sa.sa_mask); @@ -1158,18 +1162,24 @@ int init_main(int argc UNUSED_PARAM, char **argv) */ sigaction_set(SIGSTOP, &sa); /* pause */ - /* SIGINT (Ctrl-Alt-Del) must interrupt wait(), + /* These signals must interrupt wait(), * 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 */ /* First run the sysinit command */ run_actions(SYSINIT); |