Commit d3ca5874 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Michael Ellerman

powerpc/mm: Fix reporting of kernel execute faults

We currently test for is_exec and DSISR_PROTFAULT but that doesn't
make sense as this is the wrong error bit to test for an execute
permission failure.

In fact, we had code that would return early if we had an exec
fault in kernel mode so I think that was just dead code anyway.

Finally the location of that test is awkward and prevents further
simplifications.

So instead move that test into a helper along with the existing
early test for kernel exec faults and out of range accesses,
and put it all in a "bad_kernel_fault()" helper. While at it
test the correct error bits.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 65d47fd4
...@@ -180,6 +180,20 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault) ...@@ -180,6 +180,20 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
return MM_FAULT_CONTINUE; return MM_FAULT_CONTINUE;
} }
/* Is this a bad kernel fault ? */
static bool bad_kernel_fault(bool is_exec, unsigned long error_code,
unsigned long address)
{
if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT))) {
printk_ratelimited(KERN_CRIT "kernel tried to execute"
" exec-protected page (%lx) -"
"exploit attempt? (uid: %d)\n",
address, from_kuid(&init_user_ns,
current_uid()));
}
return is_exec || (address >= TASK_SIZE);
}
/* /*
* Define the correct "is_write" bit in error_code based * Define the correct "is_write" bit in error_code based
* on the processor family * on the processor family
...@@ -252,7 +266,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -252,7 +266,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
* The kernel should never take an execute fault nor should it * The kernel should never take an execute fault nor should it
* take a page fault to a kernel address. * take a page fault to a kernel address.
*/ */
if (!is_user && (is_exec || (address >= TASK_SIZE))) if (unlikely(!is_user && bad_kernel_fault(is_exec, error_code, address)))
return SIGSEGV; return SIGSEGV;
/* We restore the interrupt state now */ /* We restore the interrupt state now */
...@@ -491,11 +505,6 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -491,11 +505,6 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
return 0; return 0;
} }
if (is_exec && (error_code & DSISR_PROTFAULT))
printk_ratelimited(KERN_CRIT "kernel tried to execute NX-protected"
" page (%lx) - exploit attempt? (uid: %d)\n",
address, from_kuid(&init_user_ns, current_uid()));
return SIGSEGV; return SIGSEGV;
} }
NOKPROBE_SYMBOL(__do_page_fault); NOKPROBE_SYMBOL(__do_page_fault);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment