aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-10-31 23:11:39 -0500
committerPaul Mackerras <paulus@samba.org>2006-10-31 23:16:04 -0500
commit4393c4f6788cee65095dd838cfeca6edefbfeb52 (patch)
treebf485a8f67b2e5860fefab58eecb77a7f0d254c5 /arch/powerpc/kernel/traps.c
parent0d69a052d4d7c4085706b9ac0d1bd28ff90c9fca (diff)
[POWERPC] Make alignment exception always check exception table
The alignment exception used to only check the exception table for -EFAULT, not for other errors. That opens an oops window if we can coerce the kernel into getting an alignment exception for other reasons in what would normally be a user-protected accessor, which can be done via some of the futex ops. This fixes it by always checking the exception tables. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5ed4c2ceb5ca..c66b4771ef44 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -843,7 +843,7 @@ void __kprobes program_check_exception(struct pt_regs *regs)
843 843
844void alignment_exception(struct pt_regs *regs) 844void alignment_exception(struct pt_regs *regs)
845{ 845{
846 int fixed = 0; 846 int sig, code, fixed = 0;
847 847
848 /* we don't implement logging of alignment exceptions */ 848 /* we don't implement logging of alignment exceptions */
849 if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) 849 if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
@@ -857,14 +857,16 @@ void alignment_exception(struct pt_regs *regs)
857 857
858 /* Operand address was bad */ 858 /* Operand address was bad */
859 if (fixed == -EFAULT) { 859 if (fixed == -EFAULT) {
860 if (user_mode(regs)) 860 sig = SIGSEGV;
861 _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); 861 code = SEGV_ACCERR;
862 else 862 } else {
863 /* Search exception table */ 863 sig = SIGBUS;
864 bad_page_fault(regs, regs->dar, SIGSEGV); 864 code = BUS_ADRALN;
865 return;
866 } 865 }
867 _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); 866 if (user_mode(regs))
867 _exception(sig, regs, code, regs->dar);
868 else
869 bad_page_fault(regs, regs->dar, sig);
868} 870}
869 871
870void StackOverflow(struct pt_regs *regs) 872void StackOverflow(struct pt_regs *regs)