aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-05-08 22:03:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-05-08 22:03:19 -0400
commit89f92d6425b099538932e9b881588f87ef9f3184 (patch)
treed60eef7715df2a34459fc118fd59f7f8701cf7fd
parent8d539108560ec121d59eee05160236488266221c (diff)
parentdc5dc7e6d71ca9fd1ea01a1418150af3b2937489 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6: sparc: Fix SA_ONSTACK signal handling.
-rw-r--r--arch/sparc/kernel/signal.c20
-rw-r--r--arch/sparc64/kernel/signal.c21
-rw-r--r--arch/sparc64/kernel/signal32.c18
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
246static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) 246static 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
377static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) 377static 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