diff options
author | David S. Miller <davem@davemloft.net> | 2010-09-24 01:06:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-26 11:59:55 -0400 |
commit | 9088333e3d83a68aeac15f7810c3cbf332b80303 (patch) | |
tree | 7187e09ba5e21ee60df9c1efc6d2b8f793e64399 /arch/sparc | |
parent | caebf9103be2e6a5330c6395a1f9f213edb0c8df (diff) |
sparc32: Fix unaligned stack handling on trap return.
When the rett stack checking code sees the stack is unaligned (in both
the sun4c and srmmu cases) it jumps to the window fault-in path.
But that just tries to page the stack pages in, it doesn't do anything
special if the stack is misaligned.
Therefore we essentially just loop forever in the trap return path.
Fix this by emitting a SIGILL in the stack fault-in code if the stack
is mis-aligned.
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/mm/fault_32.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index bd8601601afa..5b836f5aea90 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c | |||
@@ -539,6 +539,12 @@ do_sigbus: | |||
539 | __do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address); | 539 | __do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address); |
540 | } | 540 | } |
541 | 541 | ||
542 | static void check_stack_aligned(unsigned long sp) | ||
543 | { | ||
544 | if (sp & 0x7UL) | ||
545 | force_sig(SIGILL, current); | ||
546 | } | ||
547 | |||
542 | void window_overflow_fault(void) | 548 | void window_overflow_fault(void) |
543 | { | 549 | { |
544 | unsigned long sp; | 550 | unsigned long sp; |
@@ -547,6 +553,8 @@ void window_overflow_fault(void) | |||
547 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) | 553 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) |
548 | force_user_fault(sp + 0x38, 1); | 554 | force_user_fault(sp + 0x38, 1); |
549 | force_user_fault(sp, 1); | 555 | force_user_fault(sp, 1); |
556 | |||
557 | check_stack_aligned(sp); | ||
550 | } | 558 | } |
551 | 559 | ||
552 | void window_underflow_fault(unsigned long sp) | 560 | void window_underflow_fault(unsigned long sp) |
@@ -554,6 +562,8 @@ void window_underflow_fault(unsigned long sp) | |||
554 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) | 562 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) |
555 | force_user_fault(sp + 0x38, 0); | 563 | force_user_fault(sp + 0x38, 0); |
556 | force_user_fault(sp, 0); | 564 | force_user_fault(sp, 0); |
565 | |||
566 | check_stack_aligned(sp); | ||
557 | } | 567 | } |
558 | 568 | ||
559 | void window_ret_fault(struct pt_regs *regs) | 569 | void window_ret_fault(struct pt_regs *regs) |
@@ -564,4 +574,6 @@ void window_ret_fault(struct pt_regs *regs) | |||
564 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) | 574 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) |
565 | force_user_fault(sp + 0x38, 0); | 575 | force_user_fault(sp + 0x38, 0); |
566 | force_user_fault(sp, 0); | 576 | force_user_fault(sp, 0); |
577 | |||
578 | check_stack_aligned(sp); | ||
567 | } | 579 | } |