Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4393c4f6 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Paul Mackerras
Browse files

[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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 0d69a052
Loading
Loading
Loading
Loading
+10 −8
Original line number Original line Diff line number Diff line
@@ -843,7 +843,7 @@ void __kprobes program_check_exception(struct pt_regs *regs)


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


	/* we don't implement logging of alignment exceptions */
	/* we don't implement logging of alignment exceptions */
	if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
	if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
@@ -857,14 +857,16 @@ void alignment_exception(struct pt_regs *regs)


	/* Operand address was bad */
	/* Operand address was bad */
	if (fixed == -EFAULT) {
	if (fixed == -EFAULT) {
		sig = SIGSEGV;
		code = SEGV_ACCERR;
	} else {
		sig = SIGBUS;
		code = BUS_ADRALN;
	}
	if (user_mode(regs))
	if (user_mode(regs))
			_exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
		_exception(sig, regs, code, regs->dar);
	else
	else
			/* Search exception table */
		bad_page_fault(regs, regs->dar, sig);
			bad_page_fault(regs, regs->dar, SIGSEGV);
		return;
	}
	_exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
}
}


void StackOverflow(struct pt_regs *regs)
void StackOverflow(struct pt_regs *regs)
+10 −8
Original line number Original line Diff line number Diff line
@@ -708,7 +708,7 @@ void single_step_exception(struct pt_regs *regs)


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


	fixed = fix_alignment(regs);
	fixed = fix_alignment(regs);
	if (fixed == 1) {
	if (fixed == 1) {
@@ -717,14 +717,16 @@ void alignment_exception(struct pt_regs *regs)
		return;
		return;
	}
	}
	if (fixed == -EFAULT) {
	if (fixed == -EFAULT) {
		/* fixed == -EFAULT means the operand address was bad */
		sig = SIGSEGV;
		code = SEGV_ACCERR;
	} else {
		sig = SIGBUS;
		code = BUS_ADRALN;
	}
	if (user_mode(regs))
	if (user_mode(regs))
			_exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
		_exception(sig, regs, code, regs->dar);
	else
	else
			bad_page_fault(regs, regs->dar, SIGSEGV);
		bad_page_fault(regs, regs->dar, sig);
		return;
	}
	_exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
}
}


void StackOverflow(struct pt_regs *regs)
void StackOverflow(struct pt_regs *regs)