From 0d88cd9394ecbcef0c733f7973504d6ff49db228 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 16 Oct 2014 08:15:46 +0000 Subject: signal.c: abort if nesting reserved signal * signal.c (check_reserved_signal): abort if reserved signal received in reserved signal handlers. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47977 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- signal.c | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/signal.c b/signal.c index d3c7cb8f32..fd7ee1bc51 100644 --- a/signal.c +++ b/signal.c @@ -799,10 +799,14 @@ check_stack_overflow(const void *addr) #define MESSAGE_FAULT_ADDRESS #endif +#if defined SIGSEGV || defined SIGBUS || defined SIGILL || defined SIGFPE +static void check_reserved_signal(const char *name); + #ifdef SIGBUS static RETSIGTYPE sigbus(int sig SIGINFO_ARG) { + check_reserved_signal("BUS"); /* * Mac OS X makes KERN_PROTECTION_FAILURE when thread touch guard page. * and it's delivered as SIGBUS instead of SIGSEGV to userland. It's crazy @@ -815,7 +819,6 @@ sigbus(int sig SIGINFO_ARG) } #endif -#ifdef SIGSEGV static void ruby_abort(void) { @@ -830,25 +833,49 @@ ruby_abort(void) } -static int segv_received = 0; extern int ruby_disable_gc; +#ifdef SIGSEGV static RETSIGTYPE sigsegv(int sig SIGINFO_ARG) { - if (segv_received) { + check_reserved_signal("SEGV"); + CHECK_STACK_OVERFLOW(); + rb_bug_context(SIGINFO_CTX, "Segmentation fault" MESSAGE_FAULT_ADDRESS); +} +#endif + +#ifdef SIGILL +static RETSIGTYPE +sigill(int sig SIGINFO_ARG) +{ + check_reserved_signal("ILL"); +#if defined __APPLE__ + CHECK_STACK_OVERFLOW(); +#endif + rb_bug_context(SIGINFO_CTX, "Illegal instruction" MESSAGE_FAULT_ADDRESS); +} +#endif + +static void +check_reserved_signal(const char *name) +{ + static const char *received; + const char *prev = ATOMIC_PTR_EXCHANGE(received, name); + + if (prev) { ssize_t RB_UNUSED_VAR(err); - static const char msg[] = "SEGV received in SEGV handler\n"; + static const char msg1[] = " received in "; + static const char msg2[] = " handler\n"; - err = write(2, msg, sizeof(msg)); + err = write(2, name, strlen(name)); + err = write(2, msg1, sizeof(msg1)); + err = write(2, prev, strlen(prev)); + err = write(2, msg2, sizeof(msg2)); ruby_abort(); } - CHECK_STACK_OVERFLOW(); - - segv_received = 1; ruby_disable_gc = 1; - rb_bug_context(SIGINFO_CTX, "Segmentation fault" MESSAGE_FAULT_ADDRESS); } #endif @@ -1381,6 +1408,9 @@ Init_signal(void) #ifdef SIGBUS install_sighandler(SIGBUS, (sighandler_t)sigbus); #endif +#ifdef SIGILL + install_sighandler(SIGILL, (sighandler_t)sigill); +#endif #ifdef SIGSEGV # ifdef USE_SIGALTSTACK rb_register_sigaltstack(GET_THREAD()); -- cgit v1.2.3