projects/linux·commit a7de2d2d

x86/fpu: Use get_user()/put_user() for the signal frame fields

a7de2d2d · Linus Torvalds <[email protected]> · 2026-10-19 19:23:49 -10:00

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 <[email protected]>
Commit
a7de2d2d783b4e3d29e89ddea52798d3172e4f07
Parents
05c6ad3f

Changes

2 files changed · +9 −9

FileStatusAddDelContent
arch/x86/kernel/fpu/signal.cmodified+6−6View file
arch/x86/kernel/fpu/xstate.hmodified+3−3View file

arch/x86/kernel/fpu/signal.c

View file
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 33e1284..0a82a39 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

arch/x86/kernel/fpu/xstate.h

View file
diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h
index 38a2862..1ea762e 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 */