提交 a411884e 编写于 作者: T Thomas Gleixner 提交者: Aichun Shi

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>
Signed-off-by: NAichun Shi <aichun.shi@intel.com>
上级 8cf0f1d2
......@@ -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. */
if (fx_sw->magic1 != FP_XSTATE_MAGIC1 ||
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)
goto setfx;
......@@ -98,7 +98,8 @@ static inline bool save_fsave_header(struct task_struct *tsk, void __user *buf)
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 _fpx_sw_bytes *sw_bytes;
......@@ -113,7 +114,7 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame)
return !err;
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
......@@ -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)
{
struct task_struct *tsk = current;
struct fpstate *fpstate = tsk->thread.fpu.fpstate;
int ia32_fxstate = (buf != buf_fx);
int ret;
......@@ -215,7 +217,7 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
fpregs_unlock();
if (ret) {
if (!__clear_user(buf_fx, fpu_user_xstate_size))
if (!__clear_user(buf_fx, fpstate->user_size))
goto retry;
return false;
}
......@@ -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))
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 true;
}
static int __restore_fpregs_from_user(void __user *buf, u64 xrestore,
bool fx_only)
static int __restore_fpregs_from_user(void __user *buf, u64 ufeatures,
u64 xrestore, bool fx_only)
{
if (use_xsave()) {
u64 init_bv = xfeatures_mask_uabi() & ~xrestore;
u64 init_bv = ufeatures & ~xrestore;
int ret;
if (likely(!fx_only))
......@@ -265,7 +268,8 @@ static bool restore_fpregs_from_user(void __user *buf, u64 xrestore,
retry:
fpregs_lock();
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();
if (unlikely(ret)) {
......@@ -332,7 +336,7 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
user_xfeatures = fx_sw_user.xfeatures;
} else {
user_xfeatures = XFEATURE_MASK_FPSSE;
state_size = fpu->fpstate->size;
state_size = fpu->fpstate->user_size;
}
if (likely(!ia32_fxstate)) {
......@@ -425,10 +429,11 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
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 :
fpu_user_xstate_size;
unsigned int size = fpstate->user_size;
return use_xsave() ? size + FP_XSTATE_MAGIC2_SIZE : size;
}
/*
......@@ -436,17 +441,19 @@ static inline int xstate_sigframe_size(void)
*/
bool fpu__restore_sig(void __user *buf, int ia32_frame)
{
unsigned int size = xstate_sigframe_size();
struct fpu *fpu = &current->thread.fpu;
void __user *buf_fx = buf;
bool ia32_fxstate = false;
bool success = false;
unsigned int size;
if (unlikely(!buf)) {
fpu__clear_user_states(fpu);
return true;
}
size = xstate_sigframe_size(fpu->fpstate);
ia32_frame &= (IS_ENABLED(CONFIG_X86_32) ||
IS_ENABLED(CONFIG_IA32_EMULATION));
......@@ -481,7 +488,7 @@ unsigned long
fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
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);
if (ia32_frame && use_fxsr()) {
......@@ -494,9 +501,12 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册