x86/fpu: Use copy_xstate_to_uabi_buf() in fpregs_get()
authorThomas Gleixner <tglx@linutronix.de>
Wed, 23 Jun 2021 12:01:44 +0000 (14:01 +0200)
committerBorislav Petkov <bp@suse.de>
Wed, 23 Jun 2021 15:49:47 +0000 (17:49 +0200)
Use the new functionality of copy_xstate_to_uabi_buf() to retrieve the
FX state when XSAVE* is in use. This avoids to overwrite the FPU state
buffer with fpstate_sanitize_xstate() which is error prone and duplicated
code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20210623121453.014441775@linutronix.de
arch/x86/kernel/fpu/regset.c

index ccbe25f..4b799e4 100644 (file)
@@ -210,10 +210,10 @@ static inline u32 twd_fxsr_to_i387(struct fxregs_state *fxsave)
  * FXSR floating point environment conversions.
  */
 
-void
-convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
+static void __convert_from_fxsr(struct user_i387_ia32_struct *env,
+                               struct task_struct *tsk,
+                               struct fxregs_state *fxsave)
 {
-       struct fxregs_state *fxsave = &tsk->thread.fpu.state.fxsave;
        struct _fpreg *to = (struct _fpreg *) &env->st_space[0];
        struct _fpxreg *from = (struct _fpxreg *) &fxsave->st_space[0];
        int i;
@@ -247,6 +247,12 @@ convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
                memcpy(&to[i], &from[i], sizeof(to[0]));
 }
 
+void
+convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
+{
+       __convert_from_fxsr(env, tsk, &tsk->thread.fpu.state.fxsave);
+}
+
 void convert_to_fxsr(struct fxregs_state *fxsave,
                     const struct user_i387_ia32_struct *env)
 
@@ -279,25 +285,29 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
 {
        struct fpu *fpu = &target->thread.fpu;
        struct user_i387_ia32_struct env;
+       struct fxregs_state fxsave, *fx;
 
        fpu__prepare_read(fpu);
 
-       if (!boot_cpu_has(X86_FEATURE_FPU))
+       if (!cpu_feature_enabled(X86_FEATURE_FPU))
                return fpregs_soft_get(target, regset, to);
 
-       if (!boot_cpu_has(X86_FEATURE_FXSR)) {
+       if (!cpu_feature_enabled(X86_FEATURE_FXSR)) {
                return membuf_write(&to, &fpu->state.fsave,
                                    sizeof(struct fregs_state));
        }
 
-       fpstate_sanitize_xstate(fpu);
+       if (use_xsave()) {
+               struct membuf mb = { .p = &fxsave, .left = sizeof(fxsave) };
 
-       if (to.left == sizeof(env)) {
-               convert_from_fxsr(to.p, target);
-               return 0;
+               /* Handle init state optimized xstate correctly */
+               copy_xstate_to_uabi_buf(mb, &fpu->state.xsave, XSTATE_COPY_FP);
+               fx = &fxsave;
+       } else {
+               fx = &fpu->state.fxsave;
        }
 
-       convert_from_fxsr(&env, target);
+       __convert_from_fxsr(&env, target, fx);
        return membuf_write(&to, &env, sizeof(env));
 }