x86/math-emu: Check __copy_from_user() result
authorArnd Bergmann <arnd@arndb.de>
Tue, 1 Oct 2019 14:23:34 +0000 (16:23 +0200)
committerBorislav Petkov <bp@suse.de>
Thu, 3 Oct 2019 08:51:08 +0000 (10:51 +0200)
The new __must_check annotation on __copy_from_user() successfully
identified some code that has lacked the check since at least
linux-2.1.73:

  arch/x86/math-emu/reg_ld_str.c:88:2: error: ignoring return value of \
  function declared with 'warn_unused_result' attribute [-Werror,-Wunused-result]
          __copy_from_user(sti_ptr, s, 10);
          ^~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
  arch/x86/math-emu/reg_ld_str.c:1129:2: error: ignoring return value of \
  function declared with 'warn_unused_result' attribute [-Werror,-Wunused-result]
          __copy_from_user(register_base + offset, s, other);
          ^~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  arch/x86/math-emu/reg_ld_str.c:1131:3: error: ignoring return value of \
  function declared with 'warn_unused_result' attribute [-Werror,-Wunused-result]
                  __copy_from_user(register_base, s + other, offset);
                ^~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In addition, the get_user()/put_user() helpers do not enforce a return
value check, but actually still require one. These have been missing for
even longer.

Change the internal wrappers around get_user()/put_user() to force
a signal and add a corresponding wrapper around __copy_from_user()
to check all such cases.

 [ bp: Break long lines. ]

Fixes: 257e458057e5 ("Import 2.1.73")
Fixes: 9dd819a15162 ("uaccess: add missing __must_check attributes")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Bill Metzenthen <billm@melbpc.org.au>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86-ml <x86@kernel.org>
Link: https://lkml.kernel.org/r/20191001142344.1274185-1-arnd@arndb.de
arch/x86/math-emu/fpu_system.h
arch/x86/math-emu/reg_ld_str.c

index f98a0c9..9b41391 100644 (file)
@@ -107,6 +107,8 @@ static inline bool seg_writable(struct desc_struct *d)
 #define FPU_access_ok(y,z)     if ( !access_ok(y,z) ) \
                                math_abort(FPU_info,SIGSEGV)
 #define FPU_abort              math_abort(FPU_info, SIGSEGV)
+#define FPU_copy_from_user(to, from, n)        \
+               do { if (copy_from_user(to, from, n)) FPU_abort; } while (0)
 
 #undef FPU_IGNORE_CODE_SEGV
 #ifdef FPU_IGNORE_CODE_SEGV
@@ -122,7 +124,7 @@ static inline bool seg_writable(struct desc_struct *d)
 #define        FPU_code_access_ok(z) FPU_access_ok((void __user *)FPU_EIP,z)
 #endif
 
-#define FPU_get_user(x,y)       get_user((x),(y))
-#define FPU_put_user(x,y)       put_user((x),(y))
+#define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
+#define FPU_put_user(x,y) do { if (put_user((x),(y))) FPU_abort; } while (0)
 
 #endif
index f377974..fe6246f 100644 (file)
@@ -85,7 +85,7 @@ int FPU_load_extended(long double __user *s, int stnr)
 
        RE_ENTRANT_CHECK_OFF;
        FPU_access_ok(s, 10);
-       __copy_from_user(sti_ptr, s, 10);
+       FPU_copy_from_user(sti_ptr, s, 10);
        RE_ENTRANT_CHECK_ON;
 
        return FPU_tagof(sti_ptr);
@@ -1126,9 +1126,9 @@ void frstor(fpu_addr_modes addr_modes, u_char __user *data_address)
        /* Copy all registers in stack order. */
        RE_ENTRANT_CHECK_OFF;
        FPU_access_ok(s, 80);
-       __copy_from_user(register_base + offset, s, other);
+       FPU_copy_from_user(register_base + offset, s, other);
        if (offset)
-               __copy_from_user(register_base, s + other, offset);
+               FPU_copy_from_user(register_base, s + other, offset);
        RE_ENTRANT_CHECK_ON;
 
        for (i = 0; i < 8; i++) {