[PATCH v2] arm64: print a fault message when attempting to write RO memory
Stephen Boyd
stephen.boyd at linaro.org
Fri Feb 17 07:53:05 PST 2017
Quoting James Morse (2017-02-17 03:00:39)
> On 17/02/17 01:19, Stephen Boyd wrote:
> > diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> > index 156169c6981b..8bd4e7f11c70 100644
> > --- a/arch/arm64/mm/fault.c
> > +++ b/arch/arm64/mm/fault.c
>
> > /*
> > * The kernel tried to access some page that wasn't present.
> > */
> > static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
> > unsigned int esr, struct pt_regs *regs)
> > {
> > + const char *msg;
> > /*
> > * Are we prepared to handle this kernel fault?
> > * We are almost certainly not prepared to handle instruction faults.
> > @@ -177,9 +193,19 @@ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
> > * No handler, we'll have to terminate things with extreme prejudice.
> > */
> > bust_spinlocks(1);
> > - pr_alert("Unable to handle kernel %s at virtual address %08lx\n",
> > - (addr < PAGE_SIZE) ? "NULL pointer dereference" :
> > - "paging request", addr);
> > +
> > + if (is_permission_fault(esr, regs)) {
>
> is_permission_fault() was previously guarded with a 'addr<USER_DS' check, this
> is because it assumes software-PAN is relevant.
>
> The corner case is when the kernel accesses TTBR1-mapped memory while
> software-PAN happens to have swivelled TTBR0. Translation faults will be matched
> by is_permission_fault(), but permission faults won't.
If I understand correctly, and I most definitely don't because there are
quite a few combinations, you're saying that __do_kernel_fault() could
be called if the kernel attempts to access some userspace address with
software PAN? That won't be caught in do_page_fault() with the previous
is_permission_fault() check?
>
> Juggling is_permission_fault() to look something like:
> ---%<---
> if (fsc_type == ESR_ELx_FSC_PERM)
> return true;
>
> if (addr < USER_DS && system_uses_ttbr0_pan())
> return fsc_type == ESR_ELx_FSC_FAULT &&
> (regs->pstate & PSR_PAN_BIT);
>
> return false;
> ---%<---
> ... should fix this.
But we don't need to check ec anymore?
if (ec != ESR_ELx_EC_DABT_CUR && ec != ESR_ELx_EC_IABT_CUR)
return false;
>
>
> > + if (esr & ESR_ELx_WNR)
> > + msg = "write to read-only memory";
> > + else
> > + msg = "read from unreadable memory";
> > + } else if (addr < PAGE_SIZE)
> > + msg = "NULL pointer dereference";
> > + else
> > + msg = "paging request";
>
> Nit: {} all the way down!
Ok.
More information about the linux-arm-kernel
mailing list