From a7de2d2d783b4e3d29e89ddea52798d3172e4f07 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 19 Oct 2026 19:23:49 -1000 Subject: [PATCH] x86/fpu: Use get_user()/put_user() for the signal frame fields The FPU signal frame code reads and writes a handful of individual fields (the xstate magic words, the legacy status word, the xfeatures header and PKRU) with __get_user() and __put_user(). These rely on an access_ok() of the whole frame done earlier by the caller. Each of those accesses enables and disables user access on its own, so the up-front check saves nothing. On x86, __get_user() is even more expensive than get_user(): it does an lfence, where get_user() checks the address with a couple of plain instructions. Use get_user() and put_user(). The accesses that run with page faults disabled stay that way; get_user() and put_user() are fine there. This is part of getting rid of __get_user() and __put_user() entirely. Signed-off-by: Linus Torvalds --- arch/x86/kernel/fpu/signal.c | 12 ++++++------ arch/x86/kernel/fpu/xstate.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index 33e1284bf3e4..0a82a39ef9ae 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -48,7 +48,7 @@ static inline bool check_xstate_in_sigframe(struct fxregs_state __user *fxbuf, * fpstate layout with out copying the extended state information * in the memory layout. */ - if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size))) + if (get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size))) return false; if (likely(magic2 == FP_XSTATE_MAGIC2)) @@ -81,14 +81,14 @@ static inline bool save_fsave_header(struct task_struct *tsk, void __user *buf) convert_from_fxsr(&env, tsk); if (__copy_to_user(buf, &env, sizeof(env)) || - __put_user(xsave->i387.swd, &fp->status) || - __put_user(X86_FXSR_MAGIC, &fp->magic)) + put_user(xsave->i387.swd, &fp->status) || + put_user(X86_FXSR_MAGIC, &fp->magic)) return false; } else { struct fregs_state __user *fp = buf; u32 swd; - if (__get_user(swd, &fp->swd) || __put_user(swd, &fp->status)) + if (get_user(swd, &fp->swd) || put_user(swd, &fp->status)) return false; } @@ -128,8 +128,8 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame, if (!use_xsave()) return !err; - err |= __put_user(FP_XSTATE_MAGIC2, - (__u32 __user *)(buf + fpstate->user_size)); + err |= put_user(FP_XSTATE_MAGIC2, + (__u32 __user *)(buf + fpstate->user_size)); /* * For legacy compatible, we always set FP/SSE bits in the bit diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h index 38a2862f09d3..1ea762e93086 100644 --- a/arch/x86/kernel/fpu/xstate.h +++ b/arch/x86/kernel/fpu/xstate.h @@ -76,9 +76,9 @@ static inline int set_xfeature_in_sigframe(struct xregs_state __user *xbuf, u64 int err; /* Read the xfeatures value already saved in the user buffer */ - err = __get_user(xfeatures, &xbuf->header.xfeatures); + err = get_user(xfeatures, &xbuf->header.xfeatures); xfeatures |= mask; - err |= __put_user(xfeatures, &xbuf->header.xfeatures); + err |= put_user(xfeatures, &xbuf->header.xfeatures); return err; } @@ -99,7 +99,7 @@ static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u32 pk return err; /* Update PKRU value in the userspace xsave buffer. */ - return __put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU)); + return put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU)); } /* XSAVE/XRSTOR wrapper functions */