提交 c4112fb6 编写于 作者: T Thomas Gleixner 提交者: Lin Wang

x86/fpu/signal: Use fpstate for size and features

mainline inclusion
from mainline-v5.16-rc1
commit 5509cc78
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I590ZC
CVE: NA

Intel-SIG: commit 5509cc78 x86/fpu/signal: Use fpstate for size and features.

--------------------------------

For dynamically enabled features it's required to get the features which
are enabled for that context when restoring from sigframe.

The same applies for all signal frame size calculations.
Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
Signed-off-by: NBorislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/87ilxz5iew.ffs@tglxSigned-off-by: NLin Wang <lin.x.wang@intel.com>
上级 02e59277
...@@ -41,7 +41,7 @@ static inline bool check_xstate_in_sigframe(struct fxregs_state __user *fxbuf, ...@@ -41,7 +41,7 @@ static inline bool check_xstate_in_sigframe(struct fxregs_state __user *fxbuf,
/* Check for the first magic field and other error scenarios. */ /* Check for the first magic field and other error scenarios. */
if (fx_sw->magic1 != FP_XSTATE_MAGIC1 || if (fx_sw->magic1 != FP_XSTATE_MAGIC1 ||
fx_sw->xstate_size < min_xstate_size || fx_sw->xstate_size < min_xstate_size ||
fx_sw->xstate_size > fpu_user_xstate_size || fx_sw->xstate_size > current->thread.fpu.fpstate->user_size ||
fx_sw->xstate_size > fx_sw->extended_size) fx_sw->xstate_size > fx_sw->extended_size)
goto setfx; goto setfx;
...@@ -98,7 +98,8 @@ static inline bool save_fsave_header(struct task_struct *tsk, void __user *buf) ...@@ -98,7 +98,8 @@ static inline bool save_fsave_header(struct task_struct *tsk, void __user *buf)
return true; return true;
} }
static inline bool save_xstate_epilog(void __user *buf, int ia32_frame) static inline bool save_xstate_epilog(void __user *buf, int ia32_frame,
unsigned int usize)
{ {
struct xregs_state __user *x = buf; struct xregs_state __user *x = buf;
struct _fpx_sw_bytes *sw_bytes; struct _fpx_sw_bytes *sw_bytes;
...@@ -113,7 +114,7 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame) ...@@ -113,7 +114,7 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame)
return !err; return !err;
err |= __put_user(FP_XSTATE_MAGIC2, err |= __put_user(FP_XSTATE_MAGIC2,
(__u32 __user *)(buf + fpu_user_xstate_size)); (__u32 __user *)(buf + usize));
/* /*
* Read the xfeatures which we copied (directly from the cpu or * Read the xfeatures which we copied (directly from the cpu or
...@@ -171,6 +172,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf) ...@@ -171,6 +172,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)
bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct fpstate *fpstate = tsk->thread.fpu.fpstate;
int ia32_fxstate = (buf != buf_fx); int ia32_fxstate = (buf != buf_fx);
int ret; int ret;
...@@ -215,7 +217,7 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) ...@@ -215,7 +217,7 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
fpregs_unlock(); fpregs_unlock();
if (ret) { if (ret) {
if (!__clear_user(buf_fx, fpu_user_xstate_size)) if (!__clear_user(buf_fx, fpstate->user_size))
goto retry; goto retry;
return false; return false;
} }
...@@ -224,17 +226,18 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) ...@@ -224,17 +226,18 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
if ((ia32_fxstate || !use_fxsr()) && !save_fsave_header(tsk, buf)) if ((ia32_fxstate || !use_fxsr()) && !save_fsave_header(tsk, buf))
return false; return false;
if (use_fxsr() && !save_xstate_epilog(buf_fx, ia32_fxstate)) if (use_fxsr() &&
!save_xstate_epilog(buf_fx, ia32_fxstate, fpstate->user_size))
return false; return false;
return true; return true;
} }
static int __restore_fpregs_from_user(void __user *buf, u64 xrestore, static int __restore_fpregs_from_user(void __user *buf, u64 ufeatures,
bool fx_only) u64 xrestore, bool fx_only)
{ {
if (use_xsave()) { if (use_xsave()) {
u64 init_bv = xfeatures_mask_uabi() & ~xrestore; u64 init_bv = ufeatures & ~xrestore;
int ret; int ret;
if (likely(!fx_only)) if (likely(!fx_only))
...@@ -265,7 +268,8 @@ static bool restore_fpregs_from_user(void __user *buf, u64 xrestore, ...@@ -265,7 +268,8 @@ static bool restore_fpregs_from_user(void __user *buf, u64 xrestore,
retry: retry:
fpregs_lock(); fpregs_lock();
pagefault_disable(); pagefault_disable();
ret = __restore_fpregs_from_user(buf, xrestore, fx_only); ret = __restore_fpregs_from_user(buf, fpu->fpstate->user_xfeatures,
xrestore, fx_only);
pagefault_enable(); pagefault_enable();
if (unlikely(ret)) { if (unlikely(ret)) {
...@@ -332,7 +336,7 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx, ...@@ -332,7 +336,7 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
user_xfeatures = fx_sw_user.xfeatures; user_xfeatures = fx_sw_user.xfeatures;
} else { } else {
user_xfeatures = XFEATURE_MASK_FPSSE; user_xfeatures = XFEATURE_MASK_FPSSE;
state_size = fpu->fpstate->size; state_size = fpu->fpstate->user_size;
} }
if (likely(!ia32_fxstate)) { if (likely(!ia32_fxstate)) {
...@@ -425,10 +429,11 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx, ...@@ -425,10 +429,11 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
return success; return success;
} }
static inline int xstate_sigframe_size(void) static inline unsigned int xstate_sigframe_size(struct fpstate *fpstate)
{ {
return use_xsave() ? fpu_user_xstate_size + FP_XSTATE_MAGIC2_SIZE : unsigned int size = fpstate->user_size;
fpu_user_xstate_size;
return use_xsave() ? size + FP_XSTATE_MAGIC2_SIZE : size;
} }
/* /*
...@@ -436,17 +441,19 @@ static inline int xstate_sigframe_size(void) ...@@ -436,17 +441,19 @@ static inline int xstate_sigframe_size(void)
*/ */
bool fpu__restore_sig(void __user *buf, int ia32_frame) bool fpu__restore_sig(void __user *buf, int ia32_frame)
{ {
unsigned int size = xstate_sigframe_size();
struct fpu *fpu = &current->thread.fpu; struct fpu *fpu = &current->thread.fpu;
void __user *buf_fx = buf; void __user *buf_fx = buf;
bool ia32_fxstate = false; bool ia32_fxstate = false;
bool success = false; bool success = false;
unsigned int size;
if (unlikely(!buf)) { if (unlikely(!buf)) {
fpu__clear_user_states(fpu); fpu__clear_user_states(fpu);
return true; return true;
} }
size = xstate_sigframe_size(fpu->fpstate);
ia32_frame &= (IS_ENABLED(CONFIG_X86_32) || ia32_frame &= (IS_ENABLED(CONFIG_X86_32) ||
IS_ENABLED(CONFIG_IA32_EMULATION)); IS_ENABLED(CONFIG_IA32_EMULATION));
...@@ -481,7 +488,7 @@ unsigned long ...@@ -481,7 +488,7 @@ unsigned long
fpu__alloc_mathframe(unsigned long sp, int ia32_frame, fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
unsigned long *buf_fx, unsigned long *size) unsigned long *buf_fx, unsigned long *size)
{ {
unsigned long frame_size = xstate_sigframe_size(); unsigned long frame_size = xstate_sigframe_size(current->thread.fpu.fpstate);
*buf_fx = sp = round_down(sp - frame_size, 64); *buf_fx = sp = round_down(sp - frame_size, 64);
if (ia32_frame && use_fxsr()) { if (ia32_frame && use_fxsr()) {
...@@ -494,9 +501,12 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame, ...@@ -494,9 +501,12 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
return sp; return sp;
} }
unsigned long fpu__get_fpstate_size(void) unsigned long __init fpu__get_fpstate_size(void)
{ {
unsigned long ret = xstate_sigframe_size(); unsigned long ret = fpu_user_xstate_size;
if (use_xsave())
ret += FP_XSTATE_MAGIC2_SIZE;
/* /*
* This space is needed on (most) 32-bit kernels, or when a 32-bit * This space is needed on (most) 32-bit kernels, or when a 32-bit
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册