[patch 02/30] POWERPC: Make alignment exception always check exception table

From: Chris Wright
Date: Wed Nov 15 2006 - 21:44:47 EST


-stable review patch. If anyone has any objections, please let us know.
------------------

From: Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx>

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@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Paul Mackerras <paulus@xxxxxxxxx>
Signed-off-by: Chris Wright <chrisw@xxxxxxxxxxxx>
---
arch/powerpc/kernel/traps.c | 18 ++++++++++--------
arch/ppc/kernel/traps.c | 18 ++++++++++--------
2 files changed, 20 insertions(+), 16 deletions(-)

--- linux-2.6.18.2.orig/arch/powerpc/kernel/traps.c
+++ linux-2.6.18.2/arch/powerpc/kernel/traps.c
@@ -818,7 +818,7 @@ void __kprobes program_check_exception(s

void alignment_exception(struct pt_regs *regs)
{
- int fixed = 0;
+ int sig, code, fixed = 0;

/* we don't implement logging of alignment exceptions */
if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
@@ -832,14 +832,16 @@ void alignment_exception(struct pt_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)
--- linux-2.6.18.2.orig/arch/ppc/kernel/traps.c
+++ linux-2.6.18.2/arch/ppc/kernel/traps.c
@@ -708,7 +708,7 @@ void single_step_exception(struct pt_reg

void alignment_exception(struct pt_regs *regs)
{
- int fixed;
+ int sig, code, fixed = 0;

fixed = fix_alignment(regs);
if (fixed == 1) {
@@ -717,14 +717,16 @@ void alignment_exception(struct pt_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)

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/