void NaClSignalStackUnregister(void) { /* * Unregister the signal stack in case a fault occurs between the * thread deallocating the signal stack and exiting. Such a fault * could be unsafe if the address space were reallocated before the * fault, although that is unlikely. */ stack_t st; st.ss_size = 0; st.ss_sp = NULL; st.ss_flags = SS_DISABLE; ZLOGFAIL(sigaltstack(&st, NULL) == -1, errno, "Failed to unregister signal stack"); }
void NaClSignalStackRegister(void *stack) { /* * If we set up signal handlers, we must ensure that any thread that * runs untrusted code has an alternate signal stack set up. The * default for a new thread is to use the stack pointer from the * point at which the fault occurs, but it would not be safe to use * untrusted code's %esp/%rsp value. */ stack_t st; st.ss_size = SIGNAL_STACK_SIZE; st.ss_sp = ((uint8_t *) stack) + STACK_GUARD_SIZE; st.ss_flags = 0; ZLOGFAIL(sigaltstack(&st, NULL) == -1, errno, "Failed to register signal stack"); }
int main() { puts("-- 1 (should block) --"); struct sigaction newAction; newAction.sa_handler = (sighandler_t)sigHandler; newAction.sa_mask = 0; newAction.sa_flags = SA_ONESHOT | SA_ONSTACK | SA_RESTART; #if defined(__BEOS__) || defined(__HAIKU__) newAction.sa_userdata = (void*)kUserDataMagic; #endif sigaction(SIGALRM, &newAction, NULL); ualarm(10000, 0); wait_for_key(); puts("-- 2 (does not block, should call handler twice) --"); newAction.sa_flags = 0; sigaction(SIGALRM, &newAction, NULL); ualarm(0, 50000); wait_for_key(); wait_for_key(); ualarm(0, 0); puts("-- 3 (alternate stack, should block) --"); #if defined(__BEOS__) && !defined(__HAIKU__) set_signal_stack(sAlternateStack, SIGSTKSZ); #else stack_t newStack; newStack.ss_sp = sAlternateStack; newStack.ss_size = SIGSTKSZ; newStack.ss_flags = 0; if (sigaltstack(&newStack, NULL) != 0) fprintf(stderr, "sigaltstack() failed: %s\n", strerror(errno)); #endif newAction.sa_flags = SA_RESTART | SA_ONSTACK; sigaction(SIGALRM, &newAction, NULL); ualarm(10000, 0); wait_for_key(); puts("-- end --"); return 0; }
void print_signal_stack() { int ret_val; stack_t oss; ret_val = sigaltstack(NULL, &oss); if(ret_val) { perror("ERROR, sigaltstack failed"); exit(1); } printf("ESP of original stack: %p, top: %p, size: %ld, disabled = %s\n", oss.ss_sp, (unsigned char *)oss.ss_sp + oss.ss_size, oss.ss_size, (oss.ss_flags & SS_DISABLE) ? "true" : "false"); }
int arch_os_thread_init(struct thread *thread) { stack_t sigstack; /* Signal handlers are normally run on the main stack, but we've * swapped stacks, require that the control stack contain only * boxed data, and expands upwards while the C stack expands * downwards. */ sigstack.ss_sp = calc_altstack_base(thread); sigstack.ss_flags = 0; sigstack.ss_size = calc_altstack_size(thread); if(sigaltstack(&sigstack,0)<0) lose("Cannot sigaltstack: %s\n",strerror(errno)); return 1; /* success */ }
/* * Register the minithread clock handler by making * mini_clock_handler point to it. * * Then set the signal handler for SIGRTMAX-1 to * handle_interrupt. This signal handler will either * interrupt the minithreads, or drop the interrupt, * depending on safety conditions. * * The signals are handled on their own stack to reduce * chances of an overrun. */ void minithread_clock_init(interrupt_handler_t clock_handler){ timer_t timerid; struct sigevent sev; struct itimerspec its; struct sigaction sa; stack_t ss; mini_clock_handler = clock_handler; sem_init(&interrupt_received_sema,0,0); ss.ss_sp = malloc(SIGSTKSZ); if (ss.ss_sp == NULL){ perror("malloc."); abort(); } ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) == -1){ perror("signal stack"); abort(); } /* Establish handler for timer signal */ sa.sa_handler = (void*)handle_interrupt; sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; sa.sa_sigaction= (void*)handle_interrupt; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask,SIGRTMAX-1); sigaddset(&sa.sa_mask,SIGRTMAX-2); if (sigaction(SIGRTMAX-1, &sa, NULL) == -1) errExit("sigaction"); /* Create the timer */ sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMAX-1; sev.sigev_value.sival_ptr = &timerid; if (timer_create(CLOCK_THREAD_CPUTIME_ID, &sev, &timerid) == -1) errExit("timer_create"); /* Start the timer */ its.it_value.tv_sec = (PERIOD) / 1000000000; its.it_value.tv_nsec = (PERIOD) % 1000000000; its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec; if (timer_settime(timerid, 0, &its, NULL) == -1) errExit("timer_settime"); }
/* alternate stack for SIGSEGV */ void rb_register_sigaltstack(rb_thread_t *th) { stack_t newSS, oldSS; if (!th->altstack) rb_bug("rb_register_sigaltstack: th->altstack not initialized\n"); newSS.ss_sp = th->altstack; newSS.ss_size = ALT_STACK_SIZE; newSS.ss_flags = 0; sigaltstack(&newSS, &oldSS); /* ignore error. */ }
int main() { struct sigaction act; act.sa_handler = handler; act.sa_flags = SA_ONSTACK; sigemptyset(&act.sa_mask); if (sigaction(SIGXFSZ, &act, 0) == -1) { perror("Unexpected error while attempting to setup test " "pre-conditions"); return PTS_UNRESOLVED; } else { printf("INFO: sigaction((SIGXFSZ, &act, 0) returned successfully\n"); } if ((alt_ss.ss_sp = (void *)malloc(SIGSTKSZ)) == NULL) { perror("Unexpected error while attempting to setup test " "pre-conditions"); return PTS_UNRESOLVED; } else { printf("INFO: Successfully malloc'd alternative stack\n"); } alt_ss.ss_size = SIGSTKSZ; alt_ss.ss_flags = 0; if (sigaltstack(&alt_ss, (stack_t *)0) == -1) { perror("Unexpected error while attempting to setup test " "pre-conditions"); return PTS_UNRESOLVED; } else { printf("INFO: sigaltstack(&alt_ss, (stack_t *)0) returned successfully\n"); } if (raise(SIGXFSZ) == -1) { perror("Unexpected error while attempting to setup test " "pre-conditions"); return PTS_UNRESOLVED; } else { printf("INFO: raise(SGABRT) returned successfully\n"); } printf("Test PASSED\n"); return PTS_PASS; }
CrashHandlerSetup::CrashHandlerSetup() { #ifdef BUILD_CRASH_HANDLER if (qgetenv("QTC_USE_CRASH_HANDLER").isEmpty()) return; const QString crashHandlerPath = qApp->applicationDirPath() + QLatin1String("/qtcreator_crash_handler"); crashHandlerPathC = qstrdup(qPrintable(crashHandlerPath)); // Setup an alternative stack for the signal handler. This way we are able to handle SIGSEGV // even if the normal process stack is exhausted. stack_t ss; ss.ss_sp = signalHandlerStack = malloc(SIGSTKSZ); // Usual requirements for alternative signal stack. if (ss.ss_sp == 0) { qWarning("Warning: Could not allocate space for alternative signal stack (%s).", Q_FUNC_INFO); return; } ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, 0) == -1) { qWarning("Warning: Failed to set alternative signal stack (%s).", Q_FUNC_INFO); return; } // Install signal handler for calling the crash handler. struct sigaction sa; if (sigemptyset(&sa.sa_mask) == -1) { qWarning("Warning: Failed to empty signal set (%s).", Q_FUNC_INFO); return; } sa.sa_handler = &signalHandler; // SA_RESETHAND - Restore signal action to default after signal handler has been called. // SA_NODEFER - Don't block the signal after it was triggered (otherwise blocked signals get // inherited via fork() and execve()). Without this the signal will not be delivered to the // restarted Qt Creator. // SA_ONSTACK - Use alternative stack. sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_ONSTACK; // See "man 7 signal" for an overview of signals. // Do not add SIGPIPE here, QProcess and QTcpSocket use it. const int signalsToHandle[] = { SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGBUS, 0 }; for (int i = 0; signalsToHandle[i]; ++i) { if (sigaction(signalsToHandle[i], &sa, 0) == -1 ) { qWarning("Warning: Failed to install signal handler for signal \"%s\" (%s).", strsignal(signalsToHandle[i]), Q_FUNC_INFO); } } #endif // BUILD_CRASH_HANDLER }
static void setup_alternate_signal_stack (void) { #ifdef HAVE_SIGALTSTACK stack_t ss; /* FreeBSD versions older than 11.0 use char * for ss_sp instead of void *. This cast works with both types. */ ss.ss_sp = (char *) xmalloc (SIGSTKSZ); ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; sigaltstack(&ss, NULL); #endif }
void check_stack(void *buf, const char *label) { struct sigaltstack ss; bzero(&ss, sizeof(ss)); if (sigaltstack(NULL, &ss) != 0) err(1, "failed to get sigaltstack in %s", label); if (ss.ss_sp != buf || ss.ss_size != SIGSTKSZ || ss.ss_flags != 0) errx(1, "bad sigaltstack value in %s: " "buf=%p ss_sp=%p ss_size=%zu ss_flags=0x%x", label, buf, ss.ss_sp, ss.ss_size, ss.ss_flags); }
FatalConditionHandler::FatalConditionHandler() { isSet = true; stack_t sigStack; sigStack.ss_sp = altStackMem; sigStack.ss_size = SIGSTKSZ; sigStack.ss_flags = 0; sigaltstack(&sigStack, &oldSigStack); struct sigaction sa = { }; sa.sa_handler = handleSignal; sa.sa_flags = SA_ONSTACK; for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); } }
void AndroidCrashReport::Init() { void* libcorkscrew = dlopen("/system/lib/libcorkscrew.so", RTLD_NOW); if (libcorkscrew) { unwind_backtrace_signal_arch = (t_unwind_backtrace_signal_arch) dlsym(libcorkscrew, "unwind_backtrace_signal_arch"); if (!unwind_backtrace_signal_arch) LOGE("unwind_backtrace_signal_arch not found"); acquire_my_map_info_list = (t_acquire_my_map_info_list) dlsym(libcorkscrew, "acquire_my_map_info_list"); if (!acquire_my_map_info_list) LOGE("acquire_my_map_info_list not found"); get_backtrace_symbols = (t_get_backtrace_symbols) dlsym(libcorkscrew, "get_backtrace_symbols"); if (!get_backtrace_symbols) LOGE("get_backtrace_symbols not found"); free_backtrace_symbols = (t_free_backtrace_symbols) dlsym(libcorkscrew, "free_backtrace_symbols"); if (!free_backtrace_symbols) LOGE("free_backtrace_symbols not found"); release_my_map_info_list = (t_release_my_map_info_list) dlsym(libcorkscrew, "release_my_map_info_list"); if (!release_my_map_info_list) LOGE("release_my_map_info_list not found"); } else { LOGE("libcorkscrew not found"); } s_sigstk.ss_size = 64 * 1024; s_sigstk.ss_sp = malloc(s_sigstk.ss_size); s_sigstk.ss_flags = 0; if (sigaltstack(&s_sigstk, 0) < 0) { Logger::Error("Could not initialize alternative signal stack"); } for (int i = 0; i < fatalSignalsCount; i++) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_SIGINFO|SA_ONSTACK; sigemptyset(&sa.sa_mask); sa.sa_sigaction = &SignalHandler; if (sigaction(fatalSignals[i], &sa, NULL) != 0) { Logger::Error("Signal registration for failed:"); } } }
bool regist_signal_stack() { void* signal_stack = malloc(SIGSTKSZ); stack_t stack; memset(&stack, 0, sizeof(stack)); stack.ss_sp = (char*)signal_stack; stack.ss_size = SIGSTKSZ; if (sigaltstack(&stack, NULL) == -1) { LOG_ERROR("sigaltstack() error"); return false; } return true; }
void* setup_altstack(void) { stack_t ss; ss.ss_sp = malloc(20*1024); if (ss.ss_sp == 0) { return NULL; } ss.ss_size = 20*1024; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) == -1) { perror("sigaltstack"); return NULL; } return ss.ss_sp; }
/* alternate stack for SIGSEGV */ void rb_register_sigaltstack(rb_thread_t *th) { stack_t newSS, oldSS; if (th->altstack) return; newSS.ss_sp = th->altstack = malloc(ALT_STACK_SIZE); if (newSS.ss_sp == NULL) /* should handle error */ rb_bug("rb_register_sigaltstack. malloc error\n"); newSS.ss_size = ALT_STACK_SIZE; newSS.ss_flags = 0; sigaltstack(&newSS, &oldSS); /* ignore error. */ }
void handler(int signo) { stack_t handler_s; if (sigaltstack((stack_t *) 0, &handler_s) == -1) { perror ("Unexpected error while attempting to setup test pre-conditions"); exit(PTS_UNRESOLVED); } if (handler_s.ss_flags != SS_ONSTACK) { printf ("Test FAILED: The alternate stack's ss_flags member does not contain SS_ONSTACK even though the handler is executing on the alternate stack\n"); exit(PTS_FAIL); } }
void NaClSetSignalHandler(void) { struct sigaction action; stack_t stack; stack.ss_sp = g_nacl_altstack; stack.ss_flags = 0; stack.ss_size = NACL_ARRAY_SIZE(g_nacl_altstack); sigaltstack(&stack, (stack_t *) NULL); memset(&action, 0, sizeof action); action.sa_sigaction = NaClSignalHandler; sigfillset(&action.sa_mask); action.sa_flags = SA_ONSTACK | SA_SIGINFO; CHECK(0 == sigaction(kExpectedSignal, &action, (struct sigaction *) NULL)); }
void takedown_altstack(void* stack) { # if defined(_AIX) stack_t ss; # else struct sigaltstack ss; # endif int result; ss.ss_flags = SS_DISABLE; ss.ss_sp = (void*)47; // This value should be ignored when ss_flags is SS_DISABLE ss.ss_size = 29; // This value should be ignored when ss_flags is SS_DISABLE { result = sigaltstack(&ss, NULL); free(stack); } }
int set_alt_stack(port_tls_data_t* tlsdata, Boolean set) { stack_t sigalt; // sets alternative stack sigalt.ss_sp = tlsdata->guard_stack_addr; sigalt.ss_size = tlsdata->guard_stack_size; //#if defined(FREEBSD) sigalt.ss_flags = set ? 0 : SS_DISABLE; //#else // sigalt.ss_flags = set ? SS_ONSTACK : SS_DISABLE; //#endif if (sigaltstack(&sigalt, NULL) != 0) return errno; return 0; }
void handler(int signo LTP_ATTRIBUTE_UNUSED) { stack_t oss; printf("Caught SIGUSR2\n"); if (sigaltstack(NULL, &oss) == -1) { perror("Unexpected error while attempting to setup test " "pre-conditions"); exit(-1); } if (oss.ss_sp != current.ss_sp || oss.ss_size != current.ss_size) { printf("Test FAILED\n"); exit(-1); } }
void handler(int signo) { stack_t oss; printf("Caught SIGPIPE\n"); if (sigaltstack((stack_t *) 0, &oss) == -1) { perror("Unexpected error while attempting to setup test " "pre-conditions"); exit(-1); } if (oss.ss_sp != current.ss_sp || oss.ss_size != current.ss_size) { printf("Test FAILED\n"); exit(-1); } }
void handler(int signo) { stack_t ss; printf("Caught SIGCHLD\n"); if (sigaltstack(NULL, &ss) == -1) { perror("Unexpected error while attempting to setup test " "pre-conditions"); exit(-1); } if (ss.ss_sp != alt_ss.ss_sp || ss.ss_size != alt_ss.ss_size) { printf("Test FAILED\n"); exit(-1); } }
int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*)) { struct sigaction sa; stack_t altss; int retval; if(argc == 2 && strcmp(argv[1], crash_switch) == 0) crash_handler(logfile); cc_user_info = user_info; if(argv[0][0] == '/') snprintf(argv0, sizeof(argv0), "%s", argv[0]); else { getcwd(argv0, sizeof(argv0)); retval = strlen(argv0); snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]); } /* Set an alternate signal stack so SIGSEGVs caused by stack overflows * still run */ altss.ss_sp = altstack; altss.ss_flags = 0; altss.ss_size = sizeof(altstack); sigaltstack(&altss, NULL); memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = crash_catcher; sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK; sigemptyset(&sa.sa_mask); retval = 0; while(num_signals--) { if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE && *signals != SIGBUS) || sigaction(*signals, &sa, NULL) == -1) { *signals = 0; retval = -1; } ++signals; } return retval; }
static void signalHandlerEnable() { bool handled = false; #ifdef SHOULD_USE_SIGNAL_STACK #if !defined(_WIN32) // alternate stack on Linux for stack overflows static uint8_t alternate_stack[SIGSTKSZ]; stack_t ss = {}; ss.ss_sp = (void*) alternate_stack; ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; sigaltstack(&ss, NULL); struct sigaction sig_action = {}; sig_action.sa_sigaction = stanfordCppLibPosixSignalHandler; sigemptyset(&sig_action.sa_mask); #ifdef __APPLE__ // backtrace() doesn't work on OS X when we use an alternate stack sig_action.sa_flags = SA_SIGINFO; #else sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK; #endif // __APPLE__ sigaction(SIGSEGV, &sig_action, NULL); sigaction(SIGFPE, &sig_action, NULL); sigaction(SIGILL, &sig_action, NULL); sigaction(SIGTERM, &sig_action, NULL); sigaction(SIGABRT, &sig_action, NULL); handled = true; #endif // not win32 #endif // SHOULD_USE_SIGNAL_STACK SIGNALS_HANDLED.clear(); SIGNALS_HANDLED.push_back(SIGSEGV); SIGNALS_HANDLED.push_back(SIGILL); SIGNALS_HANDLED.push_back(SIGFPE); #ifdef SPL_AUTOGRADER_MODE SIGNALS_HANDLED.push_back(SIGINT); #else // not SPL_AUTOGRADER_MODE SIGNALS_HANDLED.push_back(SIGABRT); #endif // SPL_AUTOGRADER_MODE if (!handled) { for (int sig : SIGNALS_HANDLED) { signal(sig, stanfordCppLibSignalHandler); } } }
int main() { static char stack[SIGSTKSZ]; printf ("top of static stack near %p(%luM, %luG) \n", ADDR(&stack)); stack_t ss = { .ss_size = SIGSTKSZ, .ss_sp = stack, }; struct sigaction sa = { .sa_handler = handler, .sa_flags = SA_ONSTACK }; sigaltstack(&ss, 0); sigfillset(&sa.sa_mask); sigaction(SIGSEGV, &sa, 0); infinite_recursion(0); return 0; }
void InstallExceptionHandler() { stack_t signal_stack; signal_stack.ss_sp = malloc(SIGSTKSZ); signal_stack.ss_size = SIGSTKSZ; signal_stack.ss_flags = 0; if (sigaltstack(&signal_stack, nullptr)) PanicAlert("sigaltstack failed"); struct sigaction sa; sa.sa_handler = nullptr; sa.sa_sigaction = &sigsegv_handler; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, nullptr); #ifdef __APPLE__ sigaction(SIGBUS, &sa, nullptr); #endif }
static void install_crash_handler() { stack_t ss; struct sigaction sa; memset(&ss, 0, sizeof(ss)); memset(&sa, 0, sizeof(sa)); ss.ss_size = sizeof(g_alt_stack); ss.ss_sp = g_alt_stack; GPR_ASSERT(sigaltstack(&ss, NULL) == 0); sa.sa_flags = (int)(SA_SIGINFO | SA_ONSTACK | SA_RESETHAND); sa.sa_sigaction = crash_handler; GPR_ASSERT(sigaction(SIGILL, &sa, NULL) == 0); GPR_ASSERT(sigaction(SIGABRT, &sa, NULL) == 0); GPR_ASSERT(sigaction(SIGBUS, &sa, NULL) == 0); GPR_ASSERT(sigaction(SIGSEGV, &sa, NULL) == 0); GPR_ASSERT(sigaction(SIGTERM, &sa, NULL) == 0); GPR_ASSERT(sigaction(SIGQUIT, &sa, NULL) == 0); }
/* Handling SIGSEGV is tricky. * If we've blown the stack, we need to call the handler in its own stack. */ int signal_setup (void) { struct sigaction act; stack_t ss; ss.ss_sp = xzmalloc (SIGSTKSZ); ss.ss_flags = 0; ss.ss_size = SIGSTKSZ; if (sigaltstack (&ss, NULL) < 0) return -1; memset (&act, 0, sizeof (act)); sigemptyset (&act.sa_mask); act.sa_handler = sigsegv_handler; act.sa_flags = SA_ONSTACK; return sigaction (SIGSEGV, &act, NULL); }
static void signal_init_altstack(char *err, size_t err_len, stack_t *alt_stack) { /* Set up alternate stack */ alt_stack->ss_sp = calloc(1, SIGSTKSZ); if (!alt_stack->ss_sp) { snprintf(err, err_len, "signal_init_altstack: failed to " "allocate %d bytes for alternate stack.", SIGSTKSZ); return; } alt_stack->ss_size = SIGSTKSZ; if (sigaltstack(alt_stack, NULL)) { int ret = errno; snprintf(err, err_len, "signal_init_altstack: sigaltstack " "failed with error %d", ret); free(alt_stack->ss_sp); return; } }