Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

powerpc/mm: Support execute-only memory on the Radix MMU

Add support for execute-only memory (XOM) for the Radix MMU by using an
execute-only mapping, as opposed to the RX mapping used by powerpc's
other MMUs.

The Hash MMU already supports XOM through the execute-only pkey,
which is a separate mechanism shared with x86. A PROT_EXEC-only mapping
will map to RX, and then the pkey will be applied on top of it.

mmap() and mprotect() consumers in userspace should observe the same
behaviour on Hash and Radix despite the differences in implementation.

Replacing the vma_is_accessible() check in access_error() with a read
check should be functionally equivalent for non-Radix MMUs, since it
follows write and execute checks. For Radix, the change enables
detecting faults on execute-only mappings where vma_is_accessible() would
return true.

Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220817050640.406017-1-ruscur@russell.cc

authored by

Russell Currey and committed by
Michael Ellerman
395cac77 4c14d7a3

+16 -3
+2
arch/powerpc/include/asm/book3s/64/pgtable.h
··· 151 151 #define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) 152 152 #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_READ) 153 153 #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) 154 + /* Radix only, Hash uses PAGE_READONLY_X + execute-only pkey instead */ 155 + #define PAGE_EXECONLY __pgprot(_PAGE_BASE | _PAGE_EXEC) 154 156 155 157 /* Permission masks used for kernel mappings */ 156 158 #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
+9 -2
arch/powerpc/mm/book3s64/pgtable.c
··· 553 553 554 554 pgprot_t vm_get_page_prot(unsigned long vm_flags) 555 555 { 556 - unsigned long prot = pgprot_val(protection_map[vm_flags & 557 - (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]); 556 + unsigned long prot; 557 + 558 + /* Radix supports execute-only, but protection_map maps X -> RX */ 559 + if (radix_enabled() && ((vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)) { 560 + prot = pgprot_val(PAGE_EXECONLY); 561 + } else { 562 + prot = pgprot_val(protection_map[vm_flags & 563 + (VM_ACCESS_FLAGS | VM_SHARED)]); 564 + } 558 565 559 566 if (vm_flags & VM_SAO) 560 567 prot |= _PAGE_SAO;
+5 -1
arch/powerpc/mm/fault.c
··· 270 270 return false; 271 271 } 272 272 273 - if (unlikely(!vma_is_accessible(vma))) 273 + /* 274 + * Check for a read fault. This could be caused by a read on an 275 + * inaccessible page (i.e. PROT_NONE), or a Radix MMU execute-only page. 276 + */ 277 + if (unlikely(!(vma->vm_flags & VM_READ))) 274 278 return true; 275 279 /* 276 280 * We should ideally do the vma pkey access check here. But in the