diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-11-20 22:45:49 +0100 |
---|---|---|
committer | Adrian Bunk <bunk@stusta.de> | 2006-11-20 22:45:49 +0100 |
commit | 371899a77a7a4e8d7f973846d2f8c16bf0722825 (patch) | |
tree | acfa0969982f568630b21cd9960026a96f297a51 | |
parent | 70c505610f4cda24c28b018db8c260c02f533a4f (diff) | |
download | lwn-371899a77a7a4e8d7f973846d2f8c16bf0722825.tar.gz lwn-371899a77a7a4e8d7f973846d2f8c16bf0722825.zip |
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: Adrian Bunk <bunk@stusta.de>
-rw-r--r-- | arch/powerpc/kernel/traps.c | 18 | ||||
-rw-r--r-- | arch/ppc/kernel/traps.c | 18 |
2 files changed, 20 insertions, 16 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 98660aedeeb7..c9506e226dd0 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -837,7 +837,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) void alignment_exception(struct pt_regs *regs) { - int fixed; + int sig, code, fixed; fixed = fix_alignment(regs); @@ -849,14 +849,16 @@ void alignment_exception(struct pt_regs *regs) /* Operand address was bad */ if (fixed == -EFAULT) { - if (user_mode(regs)) - _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); - else - /* Search exception table */ - bad_page_fault(regs, regs->dar, SIGSEGV); - return; + sig = SIGSEGV; + code = SEGV_ACCERR; + } else { + sig = SIGBUS; + code = BUS_ADRALN; } - _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); + if (user_mode(regs)) + _exception(sig, regs, code, regs->dar); + else + bad_page_fault(regs, regs->dar, sig); } void StackOverflow(struct pt_regs *regs) diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 6d0a1838d94c..aa9dd0d07ec9 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -711,7 +711,7 @@ void single_step_exception(struct pt_regs *regs) void alignment_exception(struct pt_regs *regs) { - int fixed; + int sig, code, fixed = 0; fixed = fix_alignment(regs); if (fixed == 1) { @@ -720,14 +720,16 @@ void alignment_exception(struct pt_regs *regs) return; } if (fixed == -EFAULT) { - /* fixed == -EFAULT means the operand address was bad */ - if (user_mode(regs)) - _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); - else - bad_page_fault(regs, regs->dar, SIGSEGV); - return; + sig = SIGSEGV; + code = SEGV_ACCERR; + } else { + sig = SIGBUS; + code = BUS_ADRALN; } - _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); + if (user_mode(regs)) + _exception(sig, regs, code, regs->dar); + else + bad_page_fault(regs, regs->dar, sig); } void StackOverflow(struct pt_regs *regs) |