diff options
Diffstat (limited to 'debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch')
-rw-r--r-- | debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch | 196 |
1 files changed, 0 insertions, 196 deletions
diff --git a/debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch b/debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch deleted file mode 100644 index 8f43994f5..000000000 --- a/debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch +++ /dev/null @@ -1,196 +0,0 @@ -From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> -Date: Tue, 27 Nov 2018 17:48:32 +0100 -Subject: [PATCH 21/27] x86/fpu: Let __fpu__restore_sig() restore the - !32bit+fxsr frame from kernel memory -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.0/older/patches-5.0.10-rt7.tar.xz - -The !32bit+fxsr case loads the new state from user memory. In case we -restore the FPU state on return to userland we can't do this. It would -be required to disable preemption in order to avoid a context switch -which would set TIF_NEED_FPU_LOAD. If this happens before the "restore" -operation then the loaded registers would become volatile. - -Disabling preemption while accessing user memory requires to disable the -pagefault handler. An error during XRSTOR would then mean that either a -page fault occured (and we have to retry with enabled page fault -handler) or a #GP occured because the xstate is bogus (after all the -sig-handler can modify it). - -In order to avoid that mess, copy the FPU state from userland, validate -it and then load it. The copy_users_…() helper are basically the old -helper except that they operate on kernel memory and the fault handler -just sets the error value and the caller handles it. - -copy_user_to_fpregs_zeroing() and its helpers remain and will be used -later for a fastpath optimisation. - -Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> ---- - arch/x86/include/asm/fpu/internal.h | 43 ++++++++++++++++++++++++ - arch/x86/kernel/fpu/signal.c | 62 ++++++++++++++++++++++++++++-------- - 2 files changed, 92 insertions(+), 13 deletions(-) - ---- a/arch/x86/include/asm/fpu/internal.h -+++ b/arch/x86/include/asm/fpu/internal.h -@@ -121,6 +121,21 @@ extern void fpstate_sanitize_xstate(stru - err; \ - }) - -+#define kernel_insn_err(insn, output, input...) \ -+({ \ -+ int err; \ -+ asm volatile("1:" #insn "\n\t" \ -+ "2:\n" \ -+ ".section .fixup,\"ax\"\n" \ -+ "3: movl $-1,%[err]\n" \ -+ " jmp 2b\n" \ -+ ".previous\n" \ -+ _ASM_EXTABLE(1b, 3b) \ -+ : [err] "=r" (err), output \ -+ : "0"(0), input); \ -+ err; \ -+}) -+ - #define kernel_insn(insn, output, input...) \ - asm volatile("1:" #insn "\n\t" \ - "2:\n" \ -@@ -157,6 +172,14 @@ static inline void copy_kernel_to_fxregs - } - } - -+static inline int copy_kernel_to_fxregs_err(struct fxregs_state *fx) -+{ -+ if (IS_ENABLED(CONFIG_X86_32)) -+ return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); -+ else -+ return kernel_insn_err(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx)); -+} -+ - static inline int copy_user_to_fxregs(struct fxregs_state __user *fx) - { - if (IS_ENABLED(CONFIG_X86_32)) -@@ -174,6 +197,11 @@ static inline void copy_kernel_to_fregs( - kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); - } - -+static inline int copy_kernel_to_fregs_err(struct fregs_state *fx) -+{ -+ return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); -+} -+ - static inline int copy_user_to_fregs(struct fregs_state __user *fx) - { - return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); -@@ -398,6 +426,21 @@ static inline int copy_user_to_xregs(str - - return err; - } -+ -+/* -+ * Restore xstate from kernel space xsave area, return an error code instead an -+ * exception. -+ */ -+static inline int copy_kernel_to_xregs_err(struct xregs_state *xstate, u64 mask) -+{ -+ u32 lmask = mask; -+ u32 hmask = mask >> 32; -+ int err; -+ -+ XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); -+ -+ return err; -+} - - /* - * These must be called with preempt disabled. Returns ---- a/arch/x86/kernel/fpu/signal.c -+++ b/arch/x86/kernel/fpu/signal.c -@@ -234,7 +234,8 @@ sanitize_restored_xstate(union fpregs_st - */ - xsave->i387.mxcsr &= mxcsr_feature_mask; - -- convert_to_fxsr(&state->fxsave, ia32_env); -+ if (ia32_env) -+ convert_to_fxsr(&state->fxsave, ia32_env); - } - } - -@@ -337,28 +338,63 @@ static int __fpu__restore_sig(void __use - kfree(tmp); - return err; - } else { -+ union fpregs_state *state; -+ void *tmp; - int ret; - -+ tmp = kzalloc(sizeof(*state) + fpu_kernel_xstate_size + 64, GFP_KERNEL); -+ if (!tmp) -+ return -ENOMEM; -+ state = PTR_ALIGN(tmp, 64); -+ - /* - * For 64-bit frames and 32-bit fsave frames, restore the user - * state to the registers directly (with exceptions handled). - */ -- if (use_xsave()) { -- if ((unsigned long)buf_fx % 64 || fx_only) { -- u64 init_bv = xfeatures_mask & ~XFEATURE_MASK_FPSSE; -- copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); -- ret = copy_user_to_fxregs(buf_fx); -+ if ((unsigned long)buf_fx % 64) -+ fx_only = 1; -+ -+ if (use_xsave() && !fx_only) { -+ u64 init_bv = xfeatures_mask & ~xfeatures; -+ -+ if (using_compacted_format()) { -+ ret = copy_user_to_xstate(&state->xsave, buf_fx); - } else { -- u64 init_bv = xfeatures_mask & ~xfeatures; -- if (unlikely(init_bv)) -- copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); -- ret = copy_user_to_xregs(buf_fx, xfeatures); -+ ret = __copy_from_user(&state->xsave, buf_fx, state_size); -+ -+ if (!ret && state_size > offsetof(struct xregs_state, header)) -+ ret = validate_xstate_header(&state->xsave.header); - } -+ if (ret) -+ goto err_out; -+ sanitize_restored_xstate(state, NULL, xfeatures, -+ fx_only); -+ -+ if (unlikely(init_bv)) -+ copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); -+ ret = copy_kernel_to_xregs_err(&state->xsave, xfeatures); -+ - } else if (use_fxsr()) { -- ret = copy_user_to_fxregs(buf_fx); -- } else -- ret = copy_user_to_fregs(buf_fx); -+ ret = __copy_from_user(&state->fxsave, buf_fx, state_size); -+ if (ret) -+ goto err_out; -+ -+ if (use_xsave()) { -+ u64 init_bv = xfeatures_mask & ~XFEATURE_MASK_FPSSE; -+ copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); -+ } -+ state->fxsave.mxcsr &= mxcsr_feature_mask; -+ -+ ret = copy_kernel_to_fxregs_err(&state->fxsave); -+ } else { -+ ret = __copy_from_user(&state->fsave, buf_fx, state_size); -+ if (ret) -+ goto err_out; -+ ret = copy_kernel_to_fregs_err(&state->fsave); -+ } - -+err_out: -+ kfree(tmp); - if (ret) { - fpu__clear(fpu); - return -1; |