+ /*
+ * Stack overflow should result in a SIGSEGV signal
+ * on the alternate stack.
+ * but we have one or more guard pages after the
+ * stack top, so we would get a KERN_PROTECTION_FAILURE
+ * exception instead of KERN_INVALID_ADDRESS, resulting in
+ * a SIGBUS signal.
+ * Detect that situation and select the correct signal.
+ */
+ if (code[0] == KERN_PROTECTION_FAILURE &&
+ ux_signal == SIGBUS) {
+ user_addr_t sp, stack_min, stack_max;
+ int mask;
+ struct sigacts *ps;
+
+ sp = code[1];
+ if (ut && (ut->uu_flag & UT_VFORK))
+ p = ut->uu_proc;
+#if STACK_GROWTH_UP
+ stack_min = p->user_stack;
+ stack_max = p->user_stack + MAXSSIZ;
+#else /* STACK_GROWTH_UP */
+ stack_max = p->user_stack;
+ stack_min = p->user_stack - MAXSSIZ;
+#endif /* STACK_GROWTH_UP */
+ if (sp >= stack_min &&
+ sp < stack_max) {
+ /*
+ * This is indeed a stack overflow. Deliver a
+ * SIGSEGV signal.
+ */
+ ux_signal = SIGSEGV;
+
+ /*
+ * If the thread/process is not ready to handle
+ * SIGSEGV on an alternate stack, force-deliver
+ * SIGSEGV with a SIG_DFL handler.
+ */
+ mask = sigmask(ux_signal);
+ ps = p->p_sigacts;
+ if ((p->p_sigignore & mask) ||
+ (ut->uu_sigwait & mask) ||
+ (ut->uu_sigmask & mask) ||
+ (ps->ps_sigact[SIGSEGV] == SIG_IGN) ||
+ (! (ps->ps_sigonstack & mask))) {
+ p->p_sigignore &= ~mask;
+ p->p_sigcatch &= ~mask;
+ ps->ps_sigact[SIGSEGV] = SIG_DFL;
+ ut->uu_sigwait &= ~mask;
+ ut->uu_sigmask &= ~mask;
+ }
+ }
+ }