Commit f2c7e356 authored by Russell Currey's avatar Russell Currey Committed by Michael Ellerman

powerpc/mm: Fix false detection of read faults

To support detection of read faults with Radix execute-only memory, the
vma_is_accessible() check in access_error() (which checks for PROT_NONE)
was replaced with a check to see if VM_READ was missing, and if so,
returns true to assert the fault was caused by a bad read.

This is incorrect, as it ignores that both VM_WRITE and VM_EXEC imply
read on powerpc, as defined in protection_map[].  This causes mappings
containing VM_WRITE or VM_EXEC without VM_READ to misreport the cause of
page faults, since the MMU is still allowing reads.

Correct this by restoring the original vma_is_accessible() check for
PROT_NONE mappings, and adding a separate check for Radix PROT_EXEC-only
mappings.

Fixes: 395cac77 ("powerpc/mm: Support execute-only memory on the Radix MMU")
Reported-by: default avatarMichal Suchánek <msuchanek@suse.de>
Link: https://lore.kernel.org/r/20230308152702.GR19419@kitsune.suse.czTested-by: default avatarBenjamin Gray <bgray@linux.ibm.com>
Signed-off-by: default avatarRussell Currey <ruscur@russell.cc>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230310050834.63105-1-ruscur@russell.cc
parent 6175b70d
...@@ -271,11 +271,16 @@ static bool access_error(bool is_write, bool is_exec, struct vm_area_struct *vma ...@@ -271,11 +271,16 @@ static bool access_error(bool is_write, bool is_exec, struct vm_area_struct *vma
} }
/* /*
* Check for a read fault. This could be caused by a read on an * VM_READ, VM_WRITE and VM_EXEC all imply read permissions, as
* inaccessible page (i.e. PROT_NONE), or a Radix MMU execute-only page. * defined in protection_map[]. Read faults can only be caused by
* a PROT_NONE mapping, or with a PROT_EXEC-only mapping on Radix.
*/ */
if (unlikely(!(vma->vm_flags & VM_READ))) if (unlikely(!vma_is_accessible(vma)))
return true; return true;
if (unlikely(radix_enabled() && ((vma->vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)))
return true;
/* /*
* We should ideally do the vma pkey access check here. But in the * We should ideally do the vma pkey access check here. But in the
* fault path, handle_mm_fault() also does the same check. To avoid * fault path, handle_mm_fault() also does the same check. To avoid
......
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