Skip to content

Commit 5d6b6a6

Browse files
yyu-intel-comsuryasaimadhu
authored andcommitted
x86/fpu/xstate: Update sanitize_restored_xstate() for supervisor xstates
The function sanitize_restored_xstate() sanitizes user xstates of an XSAVE buffer by clearing bits not in the input 'xfeatures' from the buffer's header->xfeatures, effectively resetting those features back to the init state. When supervisor xstates are introduced, it is necessary to make sure only user xstates are sanitized. Ensure supervisor bits in header->xfeatures stay set and supervisor states are not modified. To make names clear, also: - Rename the function to sanitize_restored_user_xstate(). - Rename input parameter 'xfeatures' to 'user_xfeatures'. - In __fpu__restore_sig(), rename 'xfeatures' to 'user_xfeatures'. Signed-off-by: Yu-cheng Yu <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Reviewed-by: Dave Hansen <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent b860eb8 commit 5d6b6a6

File tree

1 file changed

+24
-13
lines changed

1 file changed

+24
-13
lines changed

arch/x86/kernel/fpu/signal.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
211211
}
212212

213213
static inline void
214-
sanitize_restored_xstate(union fpregs_state *state,
215-
struct user_i387_ia32_struct *ia32_env,
216-
u64 xfeatures, int fx_only)
214+
sanitize_restored_user_xstate(union fpregs_state *state,
215+
struct user_i387_ia32_struct *ia32_env,
216+
u64 user_xfeatures, int fx_only)
217217
{
218218
struct xregs_state *xsave = &state->xsave;
219219
struct xstate_header *header = &xsave->header;
@@ -226,13 +226,22 @@ sanitize_restored_xstate(union fpregs_state *state,
226226
*/
227227

228228
/*
229-
* Init the state that is not present in the memory
230-
* layout and not enabled by the OS.
229+
* 'user_xfeatures' might have bits clear which are
230+
* set in header->xfeatures. This represents features that
231+
* were in init state prior to a signal delivery, and need
232+
* to be reset back to the init state. Clear any user
233+
* feature bits which are set in the kernel buffer to get
234+
* them back to the init state.
235+
*
236+
* Supervisor state is unchanged by input from userspace.
237+
* Ensure supervisor state bits stay set and supervisor
238+
* state is not modified.
231239
*/
232240
if (fx_only)
233241
header->xfeatures = XFEATURE_MASK_FPSSE;
234242
else
235-
header->xfeatures &= xfeatures;
243+
header->xfeatures &= user_xfeatures |
244+
xfeatures_mask_supervisor();
236245
}
237246

238247
if (use_fxsr()) {
@@ -281,7 +290,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
281290
struct task_struct *tsk = current;
282291
struct fpu *fpu = &tsk->thread.fpu;
283292
struct user_i387_ia32_struct env;
284-
u64 xfeatures = 0;
293+
u64 user_xfeatures = 0;
285294
int fx_only = 0;
286295
int ret = 0;
287296

@@ -314,7 +323,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
314323
trace_x86_fpu_xstate_check_failed(fpu);
315324
} else {
316325
state_size = fx_sw_user.xstate_size;
317-
xfeatures = fx_sw_user.xfeatures;
326+
user_xfeatures = fx_sw_user.xfeatures;
318327
}
319328
}
320329

@@ -349,7 +358,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
349358
*/
350359
fpregs_lock();
351360
pagefault_disable();
352-
ret = copy_user_to_fpregs_zeroing(buf_fx, xfeatures, fx_only);
361+
ret = copy_user_to_fpregs_zeroing(buf_fx, user_xfeatures, fx_only);
353362
pagefault_enable();
354363
if (!ret) {
355364
fpregs_mark_activate();
@@ -362,7 +371,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
362371

363372

364373
if (use_xsave() && !fx_only) {
365-
u64 init_bv = xfeatures_mask_user() & ~xfeatures;
374+
u64 init_bv = xfeatures_mask_user() & ~user_xfeatures;
366375

367376
if (using_compacted_format()) {
368377
ret = copy_user_to_xstate(&fpu->state.xsave, buf_fx);
@@ -375,12 +384,13 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
375384
if (ret)
376385
goto err_out;
377386

378-
sanitize_restored_xstate(&fpu->state, envp, xfeatures, fx_only);
387+
sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures,
388+
fx_only);
379389

380390
fpregs_lock();
381391
if (unlikely(init_bv))
382392
copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
383-
ret = copy_kernel_to_xregs_err(&fpu->state.xsave, xfeatures);
393+
ret = copy_kernel_to_xregs_err(&fpu->state.xsave, user_xfeatures);
384394

385395
} else if (use_fxsr()) {
386396
ret = __copy_from_user(&fpu->state.fxsave, buf_fx, state_size);
@@ -389,7 +399,8 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
389399
goto err_out;
390400
}
391401

392-
sanitize_restored_xstate(&fpu->state, envp, xfeatures, fx_only);
402+
sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures,
403+
fx_only);
393404

394405
fpregs_lock();
395406
if (use_xsave()) {

0 commit comments

Comments
 (0)