From 334678c6e95782547f3e09e2e6093013e9f7cb8f Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Tue, 25 Nov 2014 17:43:14 -0600 Subject: [PATCH] Change various uses of signal masks to use 32-bit values (previously half the signals were essentially cut off). --- include/libbb.h | 36 +------------------------ libbb/signals.c | 4 +-- shell/hush.c | 71 +++++++++++++++++++++++++------------------------ 3 files changed, 39 insertions(+), 72 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index d52b2f5b3..8cbeabc95 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -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); -enum { - /* 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; +void bb_signals(long int sigs, sig_t f) FAST_FUNC; /* syscalls like read() will be interrupted with EINTR: */ 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): */ diff --git a/libbb/signals.c b/libbb/signals.c index f7d557fcc..2364a77a8 100644 --- a/libbb/signals.c +++ b/libbb/signals.c @@ -21,10 +21,10 @@ int FAST_FUNC sigprocmask_allsigs(int how) 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 bit = 1; + long int bit = 1; while (sigs) { if (sigs & bit) { diff --git a/shell/hush.c b/shell/hush.c index b652b6271..bf2d20bf4 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -844,9 +844,9 @@ struct globals { * The rest is cleared right before execv syscalls. * Other than these two times, never modified. */ - unsigned special_sig_mask; + unsigned long special_sig_mask; #if ENABLE_HUSH_JOB - unsigned fatal_sig_mask; + unsigned long fatal_sig_mask; # define G_fatal_sig_mask G.fatal_sig_mask #else # 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 '' (ignore) are NOT reset to defaults. We do the same. */ -enum { - SPECIAL_INTERACTIVE_SIGS = 0 - | (1 << SIGTERM) - | (1 << SIGINT) - | (1 << SIGHUP) - , - SPECIAL_JOBSTOP_SIGS = 0 +#define SPECIAL_INTERACTIVE_SIGS (0 \ + | (1L << SIGTERM) \ + | (1L << SIGINT) \ + | (1L << SIGHUP) \ + ) #if ENABLE_HUSH_JOB - | (1 << SIGTTIN) - | (1 << SIGTTOU) - | (1 << SIGTSTP) +# define SPECIAL_JOBSTOP_SIGS (0 \ + | (1L << SIGTTIN) \ + | (1L << SIGTTOU) \ + | (1L << SIGTSTP) \ + ) +#else +# define SPECIAL_JOBSTOP_SIGS 0 #endif -}; 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) { sighandler_t handler = SIG_DFL; - if (sig < sizeof(unsigned)*8) { - unsigned sigmask = (1 << sig); + if (sig < sizeof(unsigned long)*8) { + unsigned long sigmask = (1L << sig); #if ENABLE_HUSH_JOB /* is sig fatal? */ @@ -5818,7 +5819,7 @@ static void code_subshell_args(char *(*coder_fn)(char *)) #endif -static void switch_off_special_sigs(unsigned mask) +static void switch_off_special_sigs(unsigned long mask) { unsigned sig = 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). */ unsigned sig; - unsigned mask; + unsigned long mask; /* Child shells are not interactive. * 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. */ bb_signals(0 - + (1 << SIGTSTP) - + (1 << SIGTTIN) - + (1 << SIGTTOU) + + (1L << SIGTSTP) + + (1L << SIGTTIN) + + (1L << SIGTTOU) , SIG_IGN); CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */ 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; unsigned sig = 0; @@ -8099,10 +8100,10 @@ static void install_sighandlers(unsigned mask) /* Called a few times only (or even once if "sh -c") */ static void install_special_sighandlers(void) { - unsigned mask; + unsigned long mask; /* Which signals are shell-special? */ - mask = (1 << SIGQUIT) | (1 << SIGCHLD); + mask = (1L << SIGQUIT) | (1L << SIGCHLD); if (G_interactive_fd) { mask |= SPECIAL_INTERACTIVE_SIGS; 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 */ static void install_fatal_sighandlers(void) { - unsigned mask; + unsigned long mask; /* We will restore tty pgrp on these signals */ mask = 0 - + (1 << SIGILL ) * HUSH_DEBUG - + (1 << SIGFPE ) * HUSH_DEBUG - + (1 << SIGBUS ) * HUSH_DEBUG - + (1 << SIGSEGV) * HUSH_DEBUG - + (1 << SIGTRAP) * HUSH_DEBUG - + (1 << SIGABRT) + + (1L << SIGILL ) * HUSH_DEBUG + + (1L << SIGFPE ) * HUSH_DEBUG + + (1L << SIGBUS ) * HUSH_DEBUG + + (1L << SIGSEGV) * HUSH_DEBUG + + (1L << SIGTRAP) * HUSH_DEBUG + + (1L << SIGABRT) /* bash 3.2 seems to handle these just like 'fatal' ones */ - + (1 << SIGPIPE) - + (1 << SIGALRM) + + (1L << SIGPIPE) + + (1L << SIGALRM) /* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs. * if we aren't interactive... but in this case * we never want to restore pgrp on exit, and this fn is not called */ - /*+ (1 << SIGHUP )*/ - /*+ (1 << SIGTERM)*/ - /*+ (1 << SIGINT )*/ + /*+ (1L << SIGHUP )*/ + /*+ (1L << SIGTERM)*/ + /*+ (1L << SIGINT )*/ ; G_fatal_sig_mask = mask;