[PATCH v1] arm64: poe: fix stale POR_EL0 values for ptrace

Kevin Brodsky kevin.brodsky at arm.com
Wed Jan 21 06:59:22 PST 2026


On 21/01/2026 14:56, Joey Gouly wrote:
> If a process wrote to POR_EL0 and then crashed before a context switch
> happened, the coredump would contain an incorrect value for POR_EL0.

Isn't that also a problem if using ptrace(PTRACE_GETREGSET, REGSET_POE)?
Just like for fpsimd, etc.

> The value read in poe_get() would be a stale value left in thread.por_el0.  Fix
> this by reading the value from the system register, if the target thread is the
> current thread.
>
> This matches what gcs/fpsimd do.
>
> Fixes: 175198199262 ("arm64/ptrace: add support for FEAT_POE")
> Reported-by: David Spickett <david.spickett at arm.com>
> Cc: stable at vger.kernel.org
> Signed-off-by: Joey Gouly <joey.gouly at arm.com>
> Cc: Kevin Brodsky <kevin.brodsky at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> ---
>  arch/arm64/include/asm/por.h | 2 ++
>  arch/arm64/kernel/process.c  | 7 ++++++-
>  arch/arm64/kernel/ptrace.c   | 5 +++++
>  3 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/include/asm/por.h b/arch/arm64/include/asm/por.h
> index d913d5b529e4..46f1356837e2 100644
> --- a/arch/arm64/include/asm/por.h
> +++ b/arch/arm64/include/asm/por.h
> @@ -31,4 +31,6 @@ static inline bool por_elx_allows_exec(u64 por, u8 pkey)
>  	return perm & POE_X;
>  }
>  
> +void poe_preserve_current_state(void);
> +
>  #endif /* _ASM_ARM64_POR_H */
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index 489554931231..400182099784 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -665,12 +665,17 @@ static int do_set_tsc_mode(unsigned int val)
>  	return 0;
>  }
>  
> +void poe_preserve_current_state(void)
> +{
> +	current->thread.por_el0 = read_sysreg_s(SYS_POR_EL0);
> +}
> +
>  static void permission_overlay_switch(struct task_struct *next)
>  {
>  	if (!system_supports_poe())
>  		return;
>  
> -	current->thread.por_el0 = read_sysreg_s(SYS_POR_EL0);
> +	poe_preserve_current_state();
>  	if (current->thread.por_el0 != next->thread.por_el0) {
>  		write_sysreg_s(next->thread.por_el0, SYS_POR_EL0);
>  		/*
> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
> index b9bdd83fbbca..276d8ee630cd 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -37,6 +37,7 @@
>  #include <asm/gcs.h>
>  #include <asm/mte.h>
>  #include <asm/pointer_auth.h>
> +#include <asm/por.h>
>  #include <asm/stacktrace.h>
>  #include <asm/syscall.h>
>  #include <asm/traps.h>
> @@ -1486,6 +1487,10 @@ static int poe_get(struct task_struct *target,
>  	if (!system_supports_poe())
>  		return -EINVAL;
>  
> +	if (target == current) {
> +		poe_preserve_current_state();
> +	}

Nit: no need for {}.

Otherwise:

Reviewed-by: Kevin Brodsky <kevin.brodsky at arm.com>

- Kevin

> +
>  	return membuf_write(&to, &target->thread.por_el0,
>  			    sizeof(target->thread.por_el0));
>  }



More information about the linux-arm-kernel mailing list