diff options
| -rw-r--r-- | arch/sparc/kernel/signal.c | 20 | ||||
| -rw-r--r-- | arch/sparc64/kernel/signal.c | 21 | ||||
| -rw-r--r-- | arch/sparc64/kernel/signal32.c | 18 |
3 files changed, 51 insertions, 8 deletions
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 3c312290c3c2..368157926d24 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c | |||
| @@ -245,15 +245,29 @@ static inline int invalid_frame_pointer(void __user *fp, int fplen) | |||
| 245 | 245 | ||
| 246 | static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) | 246 | static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) |
| 247 | { | 247 | { |
| 248 | unsigned long sp; | 248 | unsigned long sp = regs->u_regs[UREG_FP]; |
| 249 | 249 | ||
| 250 | sp = regs->u_regs[UREG_FP]; | 250 | /* |
| 251 | * If we are on the alternate signal stack and would overflow it, don't. | ||
| 252 | * Return an always-bogus address instead so we will die with SIGSEGV. | ||
| 253 | */ | ||
| 254 | if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) | ||
| 255 | return (void __user *) -1L; | ||
| 251 | 256 | ||
| 252 | /* This is the X/Open sanctioned signal stack switching. */ | 257 | /* This is the X/Open sanctioned signal stack switching. */ |
| 253 | if (sa->sa_flags & SA_ONSTACK) { | 258 | if (sa->sa_flags & SA_ONSTACK) { |
| 254 | if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) | 259 | if (sas_ss_flags(sp) == 0) |
| 255 | sp = current->sas_ss_sp + current->sas_ss_size; | 260 | sp = current->sas_ss_sp + current->sas_ss_size; |
| 256 | } | 261 | } |
| 262 | |||
| 263 | /* Always align the stack frame. This handles two cases. First, | ||
| 264 | * sigaltstack need not be mindful of platform specific stack | ||
| 265 | * alignment. Second, if we took this signal because the stack | ||
| 266 | * is not aligned properly, we'd like to take the signal cleanly | ||
| 267 | * and report that. | ||
| 268 | */ | ||
| 269 | sp &= ~7UL; | ||
| 270 | |||
| 257 | return (void __user *)(sp - framesize); | 271 | return (void __user *)(sp - framesize); |
| 258 | } | 272 | } |
| 259 | 273 | ||
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 45d6bf632daa..07c0443ea3f5 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c | |||
| @@ -376,16 +376,29 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | |||
| 376 | 376 | ||
| 377 | static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) | 377 | static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) |
| 378 | { | 378 | { |
| 379 | unsigned long sp; | 379 | unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; |
| 380 | 380 | ||
| 381 | sp = regs->u_regs[UREG_FP] + STACK_BIAS; | 381 | /* |
| 382 | * If we are on the alternate signal stack and would overflow it, don't. | ||
| 383 | * Return an always-bogus address instead so we will die with SIGSEGV. | ||
| 384 | */ | ||
| 385 | if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) | ||
| 386 | return (void __user *) -1L; | ||
| 382 | 387 | ||
| 383 | /* This is the X/Open sanctioned signal stack switching. */ | 388 | /* This is the X/Open sanctioned signal stack switching. */ |
| 384 | if (ka->sa.sa_flags & SA_ONSTACK) { | 389 | if (ka->sa.sa_flags & SA_ONSTACK) { |
| 385 | if (!on_sig_stack(sp) && | 390 | if (sas_ss_flags(sp) == 0) |
| 386 | !((current->sas_ss_sp + current->sas_ss_size) & 7)) | ||
| 387 | sp = current->sas_ss_sp + current->sas_ss_size; | 391 | sp = current->sas_ss_sp + current->sas_ss_size; |
| 388 | } | 392 | } |
| 393 | |||
| 394 | /* Always align the stack frame. This handles two cases. First, | ||
| 395 | * sigaltstack need not be mindful of platform specific stack | ||
| 396 | * alignment. Second, if we took this signal because the stack | ||
| 397 | * is not aligned properly, we'd like to take the signal cleanly | ||
| 398 | * and report that. | ||
| 399 | */ | ||
| 400 | sp &= ~7UL; | ||
| 401 | |||
| 389 | return (void __user *)(sp - framesize); | 402 | return (void __user *)(sp - framesize); |
| 390 | } | 403 | } |
| 391 | 404 | ||
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 | ||
