diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-10-31 23:11:39 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-10-31 23:16:04 -0500 |
commit | 4393c4f6788cee65095dd838cfeca6edefbfeb52 (patch) | |
tree | bf485a8f67b2e5860fefab58eecb77a7f0d254c5 /arch/ppc | |
parent | 0d69a052d4d7c4085706b9ac0d1bd28ff90c9fca (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/ppc')
-rw-r--r-- | arch/ppc/kernel/traps.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index aafc8e8893d1..9661a91183b3 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c | |||
@@ -708,7 +708,7 @@ void single_step_exception(struct pt_regs *regs) | |||
708 | 708 | ||
709 | void alignment_exception(struct pt_regs *regs) | 709 | void alignment_exception(struct pt_regs *regs) |
710 | { | 710 | { |
711 | int fixed; | 711 | int sig, code, fixed = 0; |
712 | 712 | ||
713 | fixed = fix_alignment(regs); | 713 | fixed = fix_alignment(regs); |
714 | if (fixed == 1) { | 714 | if (fixed == 1) { |
@@ -717,14 +717,16 @@ void alignment_exception(struct pt_regs *regs) | |||
717 | return; | 717 | return; |
718 | } | 718 | } |
719 | if (fixed == -EFAULT) { | 719 | if (fixed == -EFAULT) { |
720 | /* fixed == -EFAULT means the operand address was bad */ | 720 | sig = SIGSEGV; |
721 | if (user_mode(regs)) | 721 | code = SEGV_ACCERR; |
722 | _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); | 722 | } else { |
723 | else | 723 | sig = SIGBUS; |
724 | bad_page_fault(regs, regs->dar, SIGSEGV); | 724 | code = BUS_ADRALN; |
725 | return; | ||
726 | } | 725 | } |
727 | _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); | 726 | if (user_mode(regs)) |
727 | _exception(sig, regs, code, regs->dar); | ||
728 | else | ||
729 | bad_page_fault(regs, regs->dar, sig); | ||
728 | } | 730 | } |
729 | 731 | ||
730 | void StackOverflow(struct pt_regs *regs) | 732 | void StackOverflow(struct pt_regs *regs) |