[PATCH v2 2/3] arm64: mm: Handle PAN faults on uaccess CPY* instructions

Robin Murphy robin.murphy at arm.com
Thu Mar 6 07:28:26 PST 2025


On 28/02/2025 5:00 pm, Kristina Martšenko wrote:
> 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.

I'd be tempted to fold the search_exception_tables() call into 
insn_may_access_user() itself, but either way,

Reviewed-by: Robin Murphy <robin.murphy at arm.com>

> Signed-off-by: Kristina Martšenko <kristina.martsenko at arm.com>
> ---
>   arch/arm64/include/asm/extable.h |  3 +++
>   arch/arm64/mm/extable.c          | 11 +++++++++++
>   arch/arm64/mm/fault.c            |  4 +++-
>   3 files changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/extable.h b/arch/arm64/include/asm/extable.h
> index 5892b8977710..0a8cb2015c97 100644
> --- a/arch/arm64/include/asm/extable.h
> +++ b/arch/arm64/include/asm/extable.h
> @@ -33,6 +33,9 @@ do {							\
>   	(b)->data = (tmp).data;				\
>   } while (0)
>   
> +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
> +				  unsigned long esr);
> +
>   #ifdef CONFIG_BPF_JIT
>   bool ex_handler_bpf(const struct exception_table_entry *ex,
>   		    struct pt_regs *regs);
> diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c
> index afb5241e4d91..f137596dda88 100644
> --- a/arch/arm64/mm/extable.c
> +++ b/arch/arm64/mm/extable.c
> @@ -20,6 +20,17 @@ static bool cpy_faulted_on_uaccess(const struct exception_table_entry *ex,
>   	return uaccess_is_write == fault_on_write;
>   }
>   
> +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
> +				  unsigned long esr)
> +{
> +	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)
>   {
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index da4854fc6150..c2f14f9c2d92 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -553,6 +553,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
>   	unsigned int mm_flags = FAULT_FLAG_DEFAULT;
>   	unsigned long addr = untagged_addr(far);
>   	struct vm_area_struct *vma;
> +	const struct exception_table_entry *ex;
>   	int si_code;
>   	int pkey = -1;
>   
> @@ -606,7 +607,8 @@ 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))
> +		ex = search_exception_tables(regs->pc);
> +		if (!ex || !extable_insn_may_access_user(ex, esr))
>   			die_kernel_fault("access to user memory outside uaccess routines",
>   					 addr, esr, regs);
>   	}



More information about the linux-arm-kernel mailing list