Skip to content

Commit 6f9866a

Browse files
KAGA-KOKOsuryasaimadhu
authored andcommitted
x86/fpu/signal: Let xrstor handle the features to init
There is no reason to do an extra XRSTOR from init_fpstate for feature bits which have been cleared by user space in the FX magic xfeatures storage. Just clear them in the task's XSTATE header and do a full restore which will put these cleared features into init state. There is no real difference in performance because the current code already does a full restore when the xfeatures bits are preserved as the signal frame setup has stored them, which is the full UABI feature set. [ bp: Use the negated mxcsr_feature_mask in the MXCSR check. ] Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Reviewed-by: Borislav Petkov <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent fcb3635 commit 6f9866a

File tree

1 file changed

+31
-58
lines changed

1 file changed

+31
-58
lines changed

arch/x86/kernel/fpu/signal.c

Lines changed: 31 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -220,36 +220,6 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
220220
return 0;
221221
}
222222

223-
static inline void
224-
sanitize_restored_user_xstate(union fpregs_state *state,
225-
struct user_i387_ia32_struct *ia32_env, u64 mask)
226-
{
227-
struct xregs_state *xsave = &state->xsave;
228-
struct xstate_header *header = &xsave->header;
229-
230-
if (use_xsave()) {
231-
/*
232-
* Clear all feature bits which are not set in mask.
233-
*
234-
* Supervisor state has to be preserved. The sigframe
235-
* restore can only modify user features, i.e. @mask
236-
* cannot contain them.
237-
*/
238-
header->xfeatures &= mask | xfeatures_mask_supervisor();
239-
}
240-
241-
if (use_fxsr()) {
242-
/*
243-
* mscsr reserved bits must be masked to zero for security
244-
* reasons.
245-
*/
246-
xsave->i387.mxcsr &= mxcsr_feature_mask;
247-
248-
if (ia32_env)
249-
convert_to_fxsr(&state->fxsave, ia32_env);
250-
}
251-
}
252-
253223
static int __restore_fpregs_from_user(void __user *buf, u64 xrestore,
254224
bool fx_only)
255225
{
@@ -352,6 +322,8 @@ static int __fpu_restore_sig(void __user *buf, void __user *buf_fx,
352322
fx_only = !fx_sw_user.magic1;
353323
state_size = fx_sw_user.xstate_size;
354324
user_xfeatures = fx_sw_user.xfeatures;
325+
} else {
326+
user_xfeatures = XFEATURE_MASK_FPSSE;
355327
}
356328

357329
if (likely(!ia32_fxstate)) {
@@ -395,54 +367,55 @@ static int __fpu_restore_sig(void __user *buf, void __user *buf_fx,
395367
set_thread_flag(TIF_NEED_FPU_LOAD);
396368
}
397369
__fpu_invalidate_fpregs_state(fpu);
370+
__cpu_invalidate_fpregs_state();
398371
fpregs_unlock();
399372

400373
if (use_xsave() && !fx_only) {
401-
u64 init_bv = xfeatures_mask_uabi() & ~user_xfeatures;
402-
403374
ret = copy_sigframe_from_user_to_xstate(&fpu->state.xsave, buf_fx);
404375
if (ret)
405376
return ret;
377+
} else {
378+
if (__copy_from_user(&fpu->state.fxsave, buf_fx,
379+
sizeof(fpu->state.fxsave)))
380+
return -EFAULT;
406381

407-
sanitize_restored_user_xstate(&fpu->state, &env, user_xfeatures);
382+
/* Reject invalid MXCSR values. */
383+
if (fpu->state.fxsave.mxcsr & ~mxcsr_feature_mask)
384+
return -EINVAL;
408385

409-
fpregs_lock();
410-
if (unlikely(init_bv))
411-
os_xrstor(&init_fpstate.xsave, init_bv);
386+
/* Enforce XFEATURE_MASK_FPSSE when XSAVE is enabled */
387+
if (use_xsave())
388+
fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FPSSE;
389+
}
390+
391+
/* Fold the legacy FP storage */
392+
convert_to_fxsr(&fpu->state.fxsave, &env);
412393

394+
fpregs_lock();
395+
if (use_xsave()) {
413396
/*
414-
* Restore previously saved supervisor xstates along with
415-
* copied-in user xstates.
397+
* Remove all UABI feature bits not set in user_xfeatures
398+
* from the memory xstate header which makes the full
399+
* restore below bring them into init state. This works for
400+
* fx_only mode as well because that has only FP and SSE
401+
* set in user_xfeatures.
402+
*
403+
* Preserve supervisor states!
416404
*/
417-
ret = os_xrstor_safe(&fpu->state.xsave,
418-
user_xfeatures | xfeatures_mask_supervisor());
405+
u64 mask = user_xfeatures | xfeatures_mask_supervisor();
419406

407+
fpu->state.xsave.header.xfeatures &= mask;
408+
ret = os_xrstor_safe(&fpu->state.xsave, xfeatures_mask_all);
420409
} else {
421-
ret = __copy_from_user(&fpu->state.fxsave, buf_fx, state_size);
422-
if (ret)
423-
return -EFAULT;
424-
425-
sanitize_restored_user_xstate(&fpu->state, &env, user_xfeatures);
426-
427-
fpregs_lock();
428-
if (use_xsave()) {
429-
u64 init_bv;
430-
431-
init_bv = xfeatures_mask_uabi() & ~XFEATURE_MASK_FPSSE;
432-
os_xrstor(&init_fpstate.xsave, init_bv);
433-
}
434-
435410
ret = fxrstor_safe(&fpu->state.fxsave);
436411
}
437412

438-
if (!ret)
413+
if (likely(!ret))
439414
fpregs_mark_activate();
440-
else
441-
fpregs_deactivate(fpu);
415+
442416
fpregs_unlock();
443417
return ret;
444418
}
445-
446419
static inline int xstate_sigframe_size(void)
447420
{
448421
return use_xsave() ? fpu_user_xstate_size + FP_XSTATE_MAGIC2_SIZE :

0 commit comments

Comments
 (0)