Skip to content

Commit abc25bb

Browse files
Wang KefengRussell King (Oracle)
authored andcommitted
ARM: 9131/1: mm: Fix PXN process with LPAE feature
When user code execution with privilege mode, it will lead to infinite loop in the page fault handler if ARM_LPAE enabled, The issue could be reproduced with "echo EXEC_USERSPACE > /sys/kernel/debug/provoke-crash/DIRECT" As Permission fault shows in ARM spec, IFSR format when using the Short-descriptor translation table format Permission fault: 01101 First level 01111 Second level IFSR format when using the Long-descriptor translation table format Permission fault: 0011LL LL bits indicate levelb. Add is_permission_fault() function to check permission fault and die if permission fault occurred under instruction fault in do_page_fault(). Fixes: 1d4d371 ("ARM: 8235/1: Support for the PXN CPU feature on ARMv7") Signed-off-by: Kefeng Wang <[email protected]> Signed-off-by: Russell King (Oracle) <[email protected]>
1 parent 2e70710 commit abc25bb

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

arch/arm/mm/fault.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,19 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
194194
#define VM_FAULT_BADMAP 0x010000
195195
#define VM_FAULT_BADACCESS 0x020000
196196

197+
static inline bool is_permission_fault(unsigned int fsr)
198+
{
199+
int fs = fsr_fs(fsr);
200+
#ifdef CONFIG_ARM_LPAE
201+
if ((fs & FS_PERM_NOLL_MASK) == FS_PERM_NOLL)
202+
return true;
203+
#else
204+
if (fs == FS_L1_PERM || fs == FS_L2_PERM)
205+
return true;
206+
#endif
207+
return false;
208+
}
209+
197210
static vm_fault_t __kprobes
198211
__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int flags,
199212
unsigned long vma_flags, struct pt_regs *regs)
@@ -253,9 +266,14 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
253266
vm_flags = VM_WRITE;
254267
}
255268

256-
if (fsr & FSR_LNX_PF)
269+
if (fsr & FSR_LNX_PF) {
257270
vm_flags = VM_EXEC;
258271

272+
if (is_permission_fault(fsr) && !user_mode(regs))
273+
die_kernel_fault("execution of memory",
274+
mm, addr, fsr, regs);
275+
}
276+
259277
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr);
260278

261279
/*

arch/arm/mm/fault.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414

1515
#ifdef CONFIG_ARM_LPAE
1616
#define FSR_FS_AEA 17
17+
#define FS_PERM_NOLL 0xC
18+
#define FS_PERM_NOLL_MASK 0x3C
1719

1820
static inline int fsr_fs(unsigned int fsr)
1921
{
2022
return fsr & FSR_FS5_0;
2123
}
2224
#else
2325
#define FSR_FS_AEA 22
26+
#define FS_L1_PERM 0xD
27+
#define FS_L2_PERM 0xF
2428

2529
static inline int fsr_fs(unsigned int fsr)
2630
{

0 commit comments

Comments
 (0)