diff -drupN a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c --- a/arch/arm64/mm/fault.c 2018-08-06 17:23:04.000000000 +0300 +++ b/arch/arm64/mm/fault.c 2022-06-12 05:28:14.000000000 +0300 @@ -249,6 +249,25 @@ static void do_bad_area(unsigned long ad #define VM_FAULT_BADMAP 0x010000 #define VM_FAULT_BADACCESS 0x020000 +static void aw_vma_pid_add(struct vm_area_struct *vma, pid_t pid) +{ + int i; + + if (vma->access_vma_num > 62) + return; + if (vma->access_vma_num == 0) { + vma->access_vma_array[0] = pid; + vma->access_vma_num++; + return; + } + for (i = 0; i < vma->access_vma_num; i++) { + if (pid == vma->access_vma_array[i]) + return; + } + vma->access_vma_array[vma->access_vma_num] = pid; + vma->access_vma_num++; +} + static int __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int mm_flags, unsigned long vm_flags, struct task_struct *tsk) @@ -277,6 +296,7 @@ good_area: goto out; } + aw_vma_pid_add(vma, current->pid); return handle_mm_fault(vma, addr & PAGE_MASK, mm_flags); check_stack: @@ -286,13 +306,19 @@ out: return fault; } -static inline bool is_permission_fault(unsigned int esr) +static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs) { unsigned int ec = ESR_ELx_EC(esr); unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE; - return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM) || - (ec == ESR_ELx_EC_IABT_CUR && fsc_type == ESR_ELx_FSC_PERM); + if (ec != ESR_ELx_EC_DABT_CUR && ec != ESR_ELx_EC_IABT_CUR) + return false; + + if (system_uses_ttbr0_pan()) + return fsc_type == ESR_ELx_FSC_FAULT && + (regs->pstate & PSR_PAN_BIT); + else + return fsc_type == ESR_ELx_FSC_PERM; } static bool is_el0_instruction_abort(unsigned int esr) @@ -332,7 +358,7 @@ static int __kprobes do_page_fault(unsig mm_flags |= FAULT_FLAG_WRITE; } - if (is_permission_fault(esr) && (addr < TASK_SIZE)) { + if (addr < TASK_SIZE && is_permission_fault(esr, regs)) { /* regs->orig_addr_limit may be 0 if we entered from EL0 */ if (regs->orig_addr_limit == KERNEL_DS) die("Accessing user space memory with fs=KERNEL_DS", regs, esr);