x86/fpu: Add debugging checks to all copy_kernel_to_*() functions
authorIngo Molnar <mingo@kernel.org>
Mon, 25 May 2015 08:59:31 +0000 (10:59 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 27 May 2015 12:11:28 +0000 (14:11 +0200)
Copying from in-kernel FPU context buffers to FPU registers are
never supposed to fault.

Add debugging checks to copy_kernel_to_fxregs() and copy_kernel_to_fregs()
to double check this assumption.

Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Bobby Powers <bobbypowers@gmail.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/fpu/internal.h

index e3bd93c8492879e96a57994b93f80f16846d34ae..eb8fa0f9d27989c5ada048747a421d9e7d28e674 100644 (file)
@@ -143,14 +143,22 @@ static inline int copy_fxregs_to_user(struct fxregs_state __user *fx)
 
 static inline int copy_kernel_to_fxregs(struct fxregs_state *fx)
 {
-       if (config_enabled(CONFIG_X86_32))
-               return check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
-       else if (config_enabled(CONFIG_AS_FXSAVEQ))
-               return check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
+       int err;
 
-       /* See comment in copy_fxregs_to_kernel() below. */
-       return check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx),
-                         "m" (*fx));
+       if (config_enabled(CONFIG_X86_32)) {
+               err = check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
+       } else {
+               if (config_enabled(CONFIG_AS_FXSAVEQ)) {
+                       err = check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
+               } else {
+                       /* See comment in copy_fxregs_to_kernel() below. */
+                       err = check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), "m" (*fx));
+               }
+       }
+       /* Copying from a kernel buffer to FPU registers should never fail: */
+       WARN_ON_FPU(err);
+
+       return err;
 }
 
 static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
@@ -167,7 +175,11 @@ static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
 
 static inline int copy_kernel_to_fregs(struct fregs_state *fx)
 {
-       return check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
+       int err = check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
+
+       WARN_ON_FPU(err);
+
+       return err;
 }
 
 static inline int copy_user_to_fregs(struct fregs_state __user *fx)