|
@@ -342,15 +342,33 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
|
|
|
|
|
|
new_sp = scr->pt.r12;
|
|
|
tramp_addr = (unsigned long) __kernel_sigtramp;
|
|
|
- if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(new_sp) == 0) {
|
|
|
- new_sp = current->sas_ss_sp + current->sas_ss_size;
|
|
|
- /*
|
|
|
- * We need to check for the register stack being on the signal stack
|
|
|
- * separately, because it's switched separately (memory stack is switched
|
|
|
- * in the kernel, register stack is switched in the signal trampoline).
|
|
|
- */
|
|
|
- if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
|
|
|
- new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
|
|
|
+ if (ka->sa.sa_flags & SA_ONSTACK) {
|
|
|
+ int onstack = sas_ss_flags(new_sp);
|
|
|
+
|
|
|
+ if (onstack == 0) {
|
|
|
+ new_sp = current->sas_ss_sp + current->sas_ss_size;
|
|
|
+ /*
|
|
|
+ * We need to check for the register stack being on the
|
|
|
+ * signal stack separately, because it's switched
|
|
|
+ * separately (memory stack is switched in the kernel,
|
|
|
+ * register stack is switched in the signal trampoline).
|
|
|
+ */
|
|
|
+ if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
|
|
|
+ new_rbs = ALIGN(current->sas_ss_sp,
|
|
|
+ sizeof(long));
|
|
|
+ } else if (onstack == SS_ONSTACK) {
|
|
|
+ unsigned long check_sp;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If we are on the alternate signal stack and would
|
|
|
+ * overflow it, don't. Return an always-bogus address
|
|
|
+ * instead so we will die with SIGSEGV.
|
|
|
+ */
|
|
|
+ check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN;
|
|
|
+ if (!likely(on_sig_stack(check_sp)))
|
|
|
+ return force_sigsegv_info(sig, (void __user *)
|
|
|
+ check_sp);
|
|
|
+ }
|
|
|
}
|
|
|
frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
|
|
|
|