firmware/br-ext-chip-allwinner/board/v83x/kernel/patches/00000-arch_arm64_mm_fault.c...

70 lines
2.1 KiB
Diff

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);