]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
arm64: mm: Handle PAN faults on uaccess CPY* instructions
authorKristina Martšenko <kristina.martsenko@arm.com>
Fri, 28 Feb 2025 17:00:05 +0000 (17:00 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Fri, 7 Mar 2025 18:28:29 +0000 (18:28 +0000)
A subsequent patch will use CPY* instructions to copy between user and
kernel memory. Add handling for PAN faults caused by an intended kernel
memory access erroneously accessing user memory, in order to make it
easier to debug kernel bugs and to keep the same behavior as with
regular loads/stores.

Signed-off-by: Kristina Martšenko <kristina.martsenko@arm.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/20250228170006.390100-3-kristina.martsenko@arm.com
[catalin.marinas@arm.com: Folded the extable search into insn_may_access_user()]
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/extable.h
arch/arm64/mm/extable.c
arch/arm64/mm/fault.c

index 5892b8977710cfd08a85cac70a74a8c2bfa0d12f..9dc39612bdf539a4314c1e5b9c6948ae18202af3 100644 (file)
@@ -33,6 +33,8 @@ do {                                                  \
        (b)->data = (tmp).data;                         \
 } while (0)
 
+bool insn_may_access_user(unsigned long addr, unsigned long esr);
+
 #ifdef CONFIG_BPF_JIT
 bool ex_handler_bpf(const struct exception_table_entry *ex,
                    struct pt_regs *regs);
index afb5241e4d91cc2889f410d34f4c6d8928dc2af9..6e0528831cd3a62d125b3720762ff407161b8b05 100644 (file)
@@ -20,6 +20,21 @@ static bool cpy_faulted_on_uaccess(const struct exception_table_entry *ex,
        return uaccess_is_write == fault_on_write;
 }
 
+bool insn_may_access_user(unsigned long addr, unsigned long esr)
+{
+       const struct exception_table_entry *ex = search_exception_tables(addr);
+
+       if (!ex)
+               return false;
+
+       switch (ex->type) {
+       case EX_TYPE_UACCESS_CPY:
+               return cpy_faulted_on_uaccess(ex, esr);
+       default:
+               return true;
+       }
+}
+
 static inline unsigned long
 get_ex_fixup(const struct exception_table_entry *ex)
 {
index da4854fc6150ae375ef55a33d4f5194ba78e5217..ec0a337891ddfc705238fe07444c085f0d48aa5c 100644 (file)
@@ -606,7 +606,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
                        die_kernel_fault("execution of user memory",
                                         addr, esr, regs);
 
-               if (!search_exception_tables(regs->pc))
+               if (!insn_may_access_user(regs->pc, esr))
                        die_kernel_fault("access to user memory outside uaccess routines",
                                         addr, esr, regs);
        }