diff options
Diffstat (limited to 'arch/sparc64/kernel/signal32.c')
-rw-r--r-- | arch/sparc64/kernel/signal32.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 9415d2c918c5..0f6b7b156efd 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c | |||
@@ -406,11 +406,27 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns | |||
406 | regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; | 406 | regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; |
407 | sp = regs->u_regs[UREG_FP]; | 407 | sp = regs->u_regs[UREG_FP]; |
408 | 408 | ||
409 | /* | ||
410 | * If we are on the alternate signal stack and would overflow it, don't. | ||
411 | * Return an always-bogus address instead so we will die with SIGSEGV. | ||
412 | */ | ||
413 | if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) | ||
414 | return (void __user *) -1L; | ||
415 | |||
409 | /* This is the X/Open sanctioned signal stack switching. */ | 416 | /* This is the X/Open sanctioned signal stack switching. */ |
410 | if (sa->sa_flags & SA_ONSTACK) { | 417 | if (sa->sa_flags & SA_ONSTACK) { |
411 | if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) | 418 | if (sas_ss_flags(sp) == 0) |
412 | sp = current->sas_ss_sp + current->sas_ss_size; | 419 | sp = current->sas_ss_sp + current->sas_ss_size; |
413 | } | 420 | } |
421 | |||
422 | /* Always align the stack frame. This handles two cases. First, | ||
423 | * sigaltstack need not be mindful of platform specific stack | ||
424 | * alignment. Second, if we took this signal because the stack | ||
425 | * is not aligned properly, we'd like to take the signal cleanly | ||
426 | * and report that. | ||
427 | */ | ||
428 | sp &= ~7UL; | ||
429 | |||
414 | return (void __user *)(sp - framesize); | 430 | return (void __user *)(sp - framesize); |
415 | } | 431 | } |
416 | 432 | ||