x86/fpu/xstate: Preserve supervisor states for the slow path in __fpu__restore_sig()
authorYu-cheng Yu <yu-cheng.yu@intel.com>
Tue, 12 May 2020 14:54:43 +0000 (07:54 -0700)
committerBorislav Petkov <bp@suse.de>
Sat, 16 May 2020 10:09:11 +0000 (12:09 +0200)
commit98265c17efa9f2279c59262cd27679aca12e0bb8
tree5463560c8616e9ed6866426d8d9350c394bef6c3
parenteeedf1533687b8e81865fdbde79eddf7c4b76c9a
x86/fpu/xstate: Preserve supervisor states for the slow path in __fpu__restore_sig()

The signal return code is responsible for taking an XSAVE buffer
present in user memory and loading it into the hardware registers. This
operation only affects user XSAVE state and never affects supervisor
state.

The fast path through this code simply points XRSTOR directly at the
user buffer. However, since user memory is not guaranteed to be always
mapped, this XRSTOR can fail. If it fails, the signal return code falls
back to a slow path which can tolerate page faults.

That slow path copies the xfeatures one by one out of the user buffer
into the task's fpu state area. However, by being in a context where it
can handle page faults, the code can also schedule.

The lazy-fpu-load code would think it has an up-to-date fpstate and
would fail to save the supervisor state when scheduling the task out.
When scheduling back in, it would likely restore stale supervisor state.

To fix that, preserve supervisor state before the slow path.  Modify
copy_user_to_fpregs_zeroing() so that if it fails, fpregs are not zeroed,
and there is no need for fpregs_deactivate() and supervisor states are
preserved.

Move set_thread_flag(TIF_NEED_FPU_LOAD) to the slow path.  Without doing
this, the fast path also needs supervisor states to be saved first.

Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20200512145444.15483-10-yu-cheng.yu@intel.com
arch/x86/kernel/fpu/signal.c