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 <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2026-10-19 19:23:49 -10:00
parent 05c6ad3f3b
commit a7de2d2d78
2 changed files with 9 additions and 9 deletions

View File

@ -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

View File

@ -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 */