Change various uses of signal masks to use 32-bit values (previously half the signals were essentially cut off).

This commit is contained in:
Stephen Heumann 2014-11-25 17:43:14 -06:00
parent 8b9da06832
commit 334678c6e9
3 changed files with 39 additions and 72 deletions

View File

@ -403,41 +403,7 @@ char *xmalloc_follow_symlinks(const char *path) FAST_FUNC RETURNS_MALLOC;
void *mempcpy(void *dst, const void *src, size_t len); void *mempcpy(void *dst, const void *src, size_t len);
enum { void bb_signals(long int sigs, sig_t f) FAST_FUNC;
/* bb_signals(BB_FATAL_SIGS, handler) catches all signals which
* otherwise would kill us, except for those resulting from bugs:
* SIGSEGV, SIGILL, SIGFPE.
* Other fatal signals not included (TODO?):
* SIGBUS Bus error (bad memory access)
* SIGPOLL Pollable event. Synonym of SIGIO
* SIGPROF Profiling timer expired
* SIGSYS Bad argument to routine
* SIGTRAP Trace/breakpoint trap
*
* The only known arch with some of these sigs not fitting
* into 32 bits is parisc (SIGXCPU=33, SIGXFSZ=34, SIGSTKFLT=36).
* Dance around with long long to guard against that...
*/
BB_FATAL_SIGS = (int)(0
+ (1LL << SIGHUP)
+ (1LL << SIGINT)
+ (1LL << SIGTERM)
+ (1LL << SIGPIPE) // Write to pipe with no readers
+ (1LL << SIGQUIT) // Quit from keyboard
+ (1LL << SIGABRT) // Abort signal from abort(3)
+ (1LL << SIGALRM) // Timer signal from alarm(2)
+ (1LL << SIGVTALRM) // Virtual alarm clock
+ (1LL << SIGXCPU) // CPU time limit exceeded
+ (1LL << SIGXFSZ) // File size limit exceeded
+ (1LL << SIGUSR1) // Yes kids, these are also fatal!
+ (1LL << SIGUSR2)
+ 0)
};
void bb_signals(int sigs, void (*f)(int)) FAST_FUNC;
/* Unlike signal() and bb_signals, sets handler with sigaction()
* and in a way that while signal handler is run, no other signals
* will be blocked; syscalls will not be restarted: */
void bb_signals_recursive_norestart(int sigs, void (*f)(int)) FAST_FUNC;
/* syscalls like read() will be interrupted with EINTR: */ /* syscalls like read() will be interrupted with EINTR: */
void signal_no_SA_RESTART_empty_mask(int sig, void (*handler)(int)) FAST_FUNC; void signal_no_SA_RESTART_empty_mask(int sig, void (*handler)(int)) FAST_FUNC;
/* syscalls like read() won't be interrupted (though select/poll will be): */ /* syscalls like read() won't be interrupted (though select/poll will be): */

View File

@ -21,10 +21,10 @@ int FAST_FUNC sigprocmask_allsigs(int how)
return sigprocmask(how, &set, NULL); return sigprocmask(how, &set, NULL);
} }
void FAST_FUNC bb_signals(int sigs, void (*f)(int)) void FAST_FUNC bb_signals(long int sigs, sig_t f)
{ {
int sig_no = 0; int sig_no = 0;
int bit = 1; long int bit = 1;
while (sigs) { while (sigs) {
if (sigs & bit) { if (sigs & bit) {

View File

@ -844,9 +844,9 @@ struct globals {
* The rest is cleared right before execv syscalls. * The rest is cleared right before execv syscalls.
* Other than these two times, never modified. * Other than these two times, never modified.
*/ */
unsigned special_sig_mask; unsigned long special_sig_mask;
#if ENABLE_HUSH_JOB #if ENABLE_HUSH_JOB
unsigned fatal_sig_mask; unsigned long fatal_sig_mask;
# define G_fatal_sig_mask G.fatal_sig_mask # define G_fatal_sig_mask G.fatal_sig_mask
#else #else
# define G_fatal_sig_mask 0 # define G_fatal_sig_mask 0
@ -1562,19 +1562,20 @@ void _exit_wrapper(int status) {
* are set to the default actions". bash interprets it so that traps which * are set to the default actions". bash interprets it so that traps which
* are set to '' (ignore) are NOT reset to defaults. We do the same. * are set to '' (ignore) are NOT reset to defaults. We do the same.
*/ */
enum { #define SPECIAL_INTERACTIVE_SIGS (0 \
SPECIAL_INTERACTIVE_SIGS = 0 | (1L << SIGTERM) \
| (1 << SIGTERM) | (1L << SIGINT) \
| (1 << SIGINT) | (1L << SIGHUP) \
| (1 << SIGHUP) )
,
SPECIAL_JOBSTOP_SIGS = 0
#if ENABLE_HUSH_JOB #if ENABLE_HUSH_JOB
| (1 << SIGTTIN) # define SPECIAL_JOBSTOP_SIGS (0 \
| (1 << SIGTTOU) | (1L << SIGTTIN) \
| (1 << SIGTSTP) | (1L << SIGTTOU) \
| (1L << SIGTSTP) \
)
#else
# define SPECIAL_JOBSTOP_SIGS 0
#endif #endif
};
static void record_pending_signo(int sig) static void record_pending_signo(int sig)
{ {
@ -1691,8 +1692,8 @@ static void sigexit_wrapper_gno(int sig, int code)
static sighandler_t pick_sighandler(unsigned sig) static sighandler_t pick_sighandler(unsigned sig)
{ {
sighandler_t handler = SIG_DFL; sighandler_t handler = SIG_DFL;
if (sig < sizeof(unsigned)*8) { if (sig < sizeof(unsigned long)*8) {
unsigned sigmask = (1 << sig); unsigned long sigmask = (1L << sig);
#if ENABLE_HUSH_JOB #if ENABLE_HUSH_JOB
/* is sig fatal? */ /* is sig fatal? */
@ -5818,7 +5819,7 @@ static void code_subshell_args(char *(*coder_fn)(char *))
#endif #endif
static void switch_off_special_sigs(unsigned mask) static void switch_off_special_sigs(unsigned long mask)
{ {
unsigned sig = 0; unsigned sig = 0;
while ((mask >>= 1) != 0) { while ((mask >>= 1) != 0) {
@ -5849,7 +5850,7 @@ static void reset_traps_to_defaults(void)
* after fork (not vfork, NOMMU doesn't use this function). * after fork (not vfork, NOMMU doesn't use this function).
*/ */
unsigned sig; unsigned sig;
unsigned mask; unsigned long mask;
/* Child shells are not interactive. /* Child shells are not interactive.
* SIGTTIN/SIGTTOU/SIGTSTP should not have special handling. * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
@ -6164,9 +6165,9 @@ static void xforked_child(void *args_struct) {
* SUSv3 says ctrl-Z should be ignored, ctrl-C should not. * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
*/ */
bb_signals(0 bb_signals(0
+ (1 << SIGTSTP) + (1L << SIGTSTP)
+ (1 << SIGTTIN) + (1L << SIGTTIN)
+ (1 << SIGTTOU) + (1L << SIGTTOU)
, SIG_IGN); , SIG_IGN);
CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */ CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
close(args->channel[0]); /* NB: close _first_, then move fd! */ close(args->channel[0]); /* NB: close _first_, then move fd! */
@ -8070,7 +8071,7 @@ static int run_and_free_list(struct pipe *pi)
} }
static void install_sighandlers(unsigned mask) static void install_sighandlers(unsigned long mask)
{ {
sighandler_t old_handler; sighandler_t old_handler;
unsigned sig = 0; unsigned sig = 0;
@ -8099,10 +8100,10 @@ static void install_sighandlers(unsigned mask)
/* Called a few times only (or even once if "sh -c") */ /* Called a few times only (or even once if "sh -c") */
static void install_special_sighandlers(void) static void install_special_sighandlers(void)
{ {
unsigned mask; unsigned long mask;
/* Which signals are shell-special? */ /* Which signals are shell-special? */
mask = (1 << SIGQUIT) | (1 << SIGCHLD); mask = (1L << SIGQUIT) | (1L << SIGCHLD);
if (G_interactive_fd) { if (G_interactive_fd) {
mask |= SPECIAL_INTERACTIVE_SIGS; mask |= SPECIAL_INTERACTIVE_SIGS;
if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */ if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
@ -8121,26 +8122,26 @@ static void install_special_sighandlers(void)
/* Set handlers to restore tty pgrp and exit */ /* Set handlers to restore tty pgrp and exit */
static void install_fatal_sighandlers(void) static void install_fatal_sighandlers(void)
{ {
unsigned mask; unsigned long mask;
/* We will restore tty pgrp on these signals */ /* We will restore tty pgrp on these signals */
mask = 0 mask = 0
+ (1 << SIGILL ) * HUSH_DEBUG + (1L << SIGILL ) * HUSH_DEBUG
+ (1 << SIGFPE ) * HUSH_DEBUG + (1L << SIGFPE ) * HUSH_DEBUG
+ (1 << SIGBUS ) * HUSH_DEBUG + (1L << SIGBUS ) * HUSH_DEBUG
+ (1 << SIGSEGV) * HUSH_DEBUG + (1L << SIGSEGV) * HUSH_DEBUG
+ (1 << SIGTRAP) * HUSH_DEBUG + (1L << SIGTRAP) * HUSH_DEBUG
+ (1 << SIGABRT) + (1L << SIGABRT)
/* bash 3.2 seems to handle these just like 'fatal' ones */ /* bash 3.2 seems to handle these just like 'fatal' ones */
+ (1 << SIGPIPE) + (1L << SIGPIPE)
+ (1 << SIGALRM) + (1L << SIGALRM)
/* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs. /* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs.
* if we aren't interactive... but in this case * if we aren't interactive... but in this case
* we never want to restore pgrp on exit, and this fn is not called * we never want to restore pgrp on exit, and this fn is not called
*/ */
/*+ (1 << SIGHUP )*/ /*+ (1L << SIGHUP )*/
/*+ (1 << SIGTERM)*/ /*+ (1L << SIGTERM)*/
/*+ (1 << SIGINT )*/ /*+ (1L << SIGINT )*/
; ;
G_fatal_sig_mask = mask; G_fatal_sig_mask = mask;