Commit 04a9f771 authored by Kristina Martšenko's avatar Kristina Martšenko Committed by Catalin Marinas
Browse files

arm64: mm: Handle PAN faults on uaccess CPY* instructions



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: default avatarKristina Martšenko <kristina.martsenko@arm.com>
Reviewed-by: default avatarRobin 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: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 653884f8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+15 −0
Original line number Diff line number Diff line
@@ -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)
{
+1 −1
Original line number Diff line number Diff line
@@ -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);
	}