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 /init | |
parent | 4e314faa0aecb66717418e9a47a4451aec59262b (diff) | |
download | busybox-w32-2bba9ad67a917de2624d427c8c107ce3e2d3d085.tar.gz busybox-w32-2bba9ad67a917de2624d427c8c107ce3e2d3d085.tar.bz2 busybox-w32-2bba9ad67a917de2624d427c8c107ce3e2d3d085.zip |
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>
Diffstat (limited to 'init')
-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) | |||
822 | 822 | ||
823 | /* Handler for QUIT - exec "restart" action, | 823 | /* Handler for QUIT - exec "restart" action, |
824 | * else (no such action defined) do nothing */ | 824 | * else (no such action defined) do nothing */ |
825 | static void restart_handler(int sig UNUSED_PARAM) | 825 | static void exec_restart_action(void) |
826 | { | 826 | { |
827 | struct init_action *a; | 827 | struct init_action *a; |
828 | 828 | ||
@@ -975,6 +975,20 @@ static int check_delayed_sigs(void) | |||
975 | #endif | 975 | #endif |
976 | if (sig == SIGINT) | 976 | if (sig == SIGINT) |
977 | run_actions(CTRLALTDEL); | 977 | run_actions(CTRLALTDEL); |
978 | if (sig == SIGQUIT) { | ||
979 | exec_restart_action(); | ||
980 | /* returns only if no restart action defined */ | ||
981 | } | ||
982 | if ((1 << sig) & (0 | ||
983 | #ifdef SIGPWR | ||
984 | + (1 << SIGPWR) | ||
985 | #endif | ||
986 | + (1 << SIGUSR1) | ||
987 | + (1 << SIGUSR2) | ||
988 | + (1 << SIGTERM) | ||
989 | )) { | ||
990 | halt_reboot_pwoff(sig); | ||
991 | } | ||
978 | } | 992 | } |
979 | } | 993 | } |
980 | 994 | ||
@@ -1070,7 +1084,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1070 | 1084 | ||
1071 | #if 0 | 1085 | #if 0 |
1072 | /* It's 2013, does anyone really still depend on this? */ | 1086 | /* It's 2013, does anyone really still depend on this? */ |
1073 | /* If you do, consider adding swapon to sysinot actions then! */ | 1087 | /* If you do, consider adding swapon to sysinit actions then! */ |
1074 | /* struct sysinfo is linux-specific */ | 1088 | /* struct sysinfo is linux-specific */ |
1075 | # ifdef __linux__ | 1089 | # ifdef __linux__ |
1076 | /* Make sure there is enough memory to do something useful. */ | 1090 | /* Make sure there is enough memory to do something useful. */ |
@@ -1134,16 +1148,6 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1134 | if (!DEBUG_INIT) { | 1148 | if (!DEBUG_INIT) { |
1135 | struct sigaction sa; | 1149 | struct sigaction sa; |
1136 | 1150 | ||
1137 | bb_signals(0 | ||
1138 | #ifdef SIGPWR | ||
1139 | + (1 << SIGPWR) /* halt */ | ||
1140 | #endif | ||
1141 | + (1 << SIGUSR1) /* halt */ | ||
1142 | + (1 << SIGTERM) /* reboot */ | ||
1143 | + (1 << SIGUSR2) /* poweroff */ | ||
1144 | , halt_reboot_pwoff); | ||
1145 | signal(SIGQUIT, restart_handler); /* re-exec another init */ | ||
1146 | |||
1147 | /* Stop handler must allow only SIGCONT inside itself */ | 1151 | /* Stop handler must allow only SIGCONT inside itself */ |
1148 | memset(&sa, 0, sizeof(sa)); | 1152 | memset(&sa, 0, sizeof(sa)); |
1149 | sigfillset(&sa.sa_mask); | 1153 | sigfillset(&sa.sa_mask); |
@@ -1158,18 +1162,24 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1158 | */ | 1162 | */ |
1159 | sigaction_set(SIGSTOP, &sa); /* pause */ | 1163 | sigaction_set(SIGSTOP, &sa); /* pause */ |
1160 | 1164 | ||
1161 | /* SIGINT (Ctrl-Alt-Del) must interrupt wait(), | 1165 | /* These signals must interrupt wait(), |
1162 | * setting handler without SA_RESTART flag. | 1166 | * setting handler without SA_RESTART flag. |
1163 | */ | 1167 | */ |
1164 | bb_signals_recursive_norestart((1 << SIGINT), record_signo); | 1168 | bb_signals_recursive_norestart(0 |
1169 | + (1 << SIGINT) /* Ctrl-Alt-Del */ | ||
1170 | + (1 << SIGQUIT) /* re-exec another init */ | ||
1171 | #ifdef SIGPWR | ||
1172 | + (1 << SIGPWR) /* halt */ | ||
1173 | #endif | ||
1174 | + (1 << SIGUSR1) /* halt */ | ||
1175 | + (1 << SIGTERM) /* reboot */ | ||
1176 | + (1 << SIGUSR2) /* poweroff */ | ||
1177 | #if ENABLE_FEATURE_USE_INITTAB | ||
1178 | + (1 << SIGHUP) /* reread /etc/inittab */ | ||
1179 | #endif | ||
1180 | , record_signo); | ||
1165 | } | 1181 | } |
1166 | 1182 | ||
1167 | /* Set up "reread /etc/inittab" handler. | ||
1168 | * Handler is set up without SA_RESTART, it will interrupt syscalls. | ||
1169 | */ | ||
1170 | if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB) | ||
1171 | bb_signals_recursive_norestart((1 << SIGHUP), record_signo); | ||
1172 | |||
1173 | /* Now run everything that needs to be run */ | 1183 | /* Now run everything that needs to be run */ |
1174 | /* First run the sysinit command */ | 1184 | /* First run the sysinit command */ |
1175 | run_actions(SYSINIT); | 1185 | run_actions(SYSINIT); |