On Tue, Jun 22 2021 at 12:17, Greg KH wrote: > On Mon, Jun 21, 2021 at 07:45:02PM +0200, Borislav Petkov wrote: >> On Mon, Jun 21, 2021 at 12:52:12PM +0200, gregkh@xxxxxxxxxxxxxxxxxxx wrote: >> > >> > The patch below does not apply to the 4.4-stable tree. >> > If someone wants it applied there, or to any other stable or longterm >> > tree, then please email the backport, including the original git commit >> > id to <stable@xxxxxxxxxxxxxxx>. >> >> Ok, how's this below? >> >> It should at least capture the gist of what this commit is trying to >> achieve as the FPU mess has changed substantially since 4.4 so I'm >> really cautious here not to break any existing setups. >> >> I've boot-tested this in a VM but Greg, I'd appreciate running it >> through some sort of stable testing framework if you're using one. > > This applied to 4.4.y and 4.9.y, but we still need a 4.14.y and 4.19.y > version if at all possible. Everything is possible :) --- Subject: x86/fpu: Reset state for all signal restore failures From: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Date: Wed Jun 9 21:18:00 2021 +0200 From: Thomas Gleixner <tglx@xxxxxxxxxxxxx> commit efa165504943f2128d50f63de0c02faf6dcceb0d upstream If access_ok() or fpregs_soft_set() fails in __fpu__restore_sig() then the function just returns but does not clear the FPU state as it does for all other fatal failures. Clear the FPU state for these failures as well. Fixes: 72a671ced66d ("x86, fpu: Unify signal handling code paths for x86 and x86_64 kernels") Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Signed-off-by: Borislav Petkov <bp@xxxxxxx> Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx Link: https://lkml.kernel.org/r/87mtryyhhz.ffs@xxxxxxxxxxxxxxxxxxxxxxx --- arch/x86/kernel/fpu/signal.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) --- --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -281,15 +281,21 @@ static int __fpu__restore_sig(void __use return 0; } - if (!access_ok(VERIFY_READ, buf, size)) - return -EACCES; + if (!access_ok(VERIFY_READ, buf, size)) { + ret = -EACCES; + goto out_err; + } fpu__initialize(fpu); - if (!static_cpu_has(X86_FEATURE_FPU)) - return fpregs_soft_set(current, NULL, - 0, sizeof(struct user_i387_ia32_struct), - NULL, buf) != 0; + if (!static_cpu_has(X86_FEATURE_FPU)) { + ret = fpregs_soft_set(current, NULL, + 0, sizeof(struct user_i387_ia32_struct), + NULL, buf) != 0; + if (ret) + goto out_err; + return 0; + } if (use_xsave()) { struct _fpx_sw_bytes fx_sw_user; @@ -349,6 +355,7 @@ static int __fpu__restore_sig(void __use fpu__restore(fpu); local_bh_enable(); + /* Failure is already handled */ return err; } else { /* @@ -356,13 +363,14 @@ static int __fpu__restore_sig(void __use * state to the registers directly (with exceptions handled). */ user_fpu_begin(); - if (copy_user_to_fpregs_zeroing(buf_fx, xfeatures, fx_only)) { - fpu__clear(fpu); - return -1; - } + if (!copy_user_to_fpregs_zeroing(buf_fx, xfeatures, fx_only)) + return 0; + ret = -1; } - return 0; +out_err: + fpu__clear(fpu); + return ret; } static inline int xstate_sigframe_size(void)