[PATCH v2 04/24] arm64/fpsimd: signal: Consistently read FPSIMD context

Will Deacon will at kernel.org
Thu May 8 07:34:23 PDT 2025


On Thu, May 08, 2025 at 02:26:24PM +0100, Mark Rutland wrote:
> For historical reasons, restore_sve_fpsimd_context() has an open-coded
> copy of the logic from read_fpsimd_context(), which is used to either
> restore an FPSIMD-only context, or to merge FPSIMD state into an
> SVE state when restoring an SVE+FPSIMD context. The logic is *almost*
> identical.
> 
> Refactor the logic to avoid duplication and make this clearer.
> 
> This comes with two functional changes that I do not believe will be
> problematic in practice:
> 
> * The user_fpsimd_state::size field will be checked in all restore paths
>   that consume it user_fpsimd_state. The kernel always populates this
>   field when delivering a signal, and so this should contain the
>   expected value unless it has been corrupted.
> 
> * If a read of user_fpsimd_state fails, we will return early without
>   modifying TIF_SVE, the saved SVCR, or the save fp_type. This will
>   leave the task in a consistent state, without potentially resurrecting
>   stale FPSIMD state. A read of user_fpsimd_state should never fail
>   unless the structure has been corrupted or the stack has been
>   unmapped.
> 
> Suggested-by: Will Deacon <will at kernel.org>
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: Mark Brown <broonie at kernel.org>
> Cc: Will Deacon <will at kernel.org>
> ---
>  arch/arm64/kernel/signal.c | 57 +++++++++++++++++++-------------------
>  1 file changed, 29 insertions(+), 28 deletions(-)
> 
> diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
> index e898948a31b65..87890d7be8de3 100644
> --- a/arch/arm64/kernel/signal.c
> +++ b/arch/arm64/kernel/signal.c
> @@ -264,30 +264,40 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
>  	return err ? -EFAULT : 0;
>  }
>  
> -static int restore_fpsimd_context(struct user_ctxs *user)
> +static int read_fpsimd_context(struct user_fpsimd_state *fpsimd,
> +			       struct user_ctxs *user)
>  {
> -	struct user_fpsimd_state fpsimd;
> -	int err = 0;
> +	int err;
>  
>  	/* check the size information */
>  	if (user->fpsimd_size != sizeof(struct fpsimd_context))
>  		return -EINVAL;
>  
>  	/* copy the FP and status/control registers */
> -	err = __copy_from_user(fpsimd.vregs, &(user->fpsimd->vregs),
> -			       sizeof(fpsimd.vregs));
> -	__get_user_error(fpsimd.fpsr, &(user->fpsimd->fpsr), err);
> -	__get_user_error(fpsimd.fpcr, &(user->fpsimd->fpcr), err);
> +	err = __copy_from_user(fpsimd->vregs, &(user->fpsimd->vregs),
> +			       sizeof(fpsimd->vregs));
> +	__get_user_error(fpsimd->fpsr, &(user->fpsimd->fpsr), err);
> +	__get_user_error(fpsimd->fpcr, &(user->fpsimd->fpcr), err);
> +
> +	return err;

I think this should return -EFAULT if 'err' is non-zero, otherwise we
can probably propagate the number of bytes not copied from
__copy_from_user().

I'll fix that up when applying.

Cheers,

Will



More information about the linux-arm-kernel mailing list