x86/mpx: Do proper get_user() when running 32-bit binaries on 64-bit kernels
[cascardo/linux.git] / arch / x86 / mm / mpx.c
index b0ae85f..6127c5e 100644 (file)
@@ -585,6 +585,29 @@ static unsigned long mpx_bd_entry_to_bt_addr(struct mm_struct *mm,
        return bt_addr;
 }
 
+/*
+ * We only want to do a 4-byte get_user() on 32-bit.  Otherwise,
+ * we might run off the end of the bounds table if we are on
+ * a 64-bit kernel and try to get 8 bytes.
+ */
+int get_user_bd_entry(struct mm_struct *mm, unsigned long *bd_entry_ret,
+               long __user *bd_entry_ptr)
+{
+       u32 bd_entry_32;
+       int ret;
+
+       if (is_64bit_mm(mm))
+               return get_user(*bd_entry_ret, bd_entry_ptr);
+
+       /*
+        * Note that get_user() uses the type of the *pointer* to
+        * establish the size of the get, not the destination.
+        */
+       ret = get_user(bd_entry_32, (u32 __user *)bd_entry_ptr);
+       *bd_entry_ret = bd_entry_32;
+       return ret;
+}
+
 /*
  * Get the base of bounds tables pointed by specific bounds
  * directory entry.
@@ -605,7 +628,7 @@ static int get_bt_addr(struct mm_struct *mm,
                int need_write = 0;
 
                pagefault_disable();
-               ret = get_user(bd_entry, bd_entry_ptr);
+               ret = get_user_bd_entry(mm, &bd_entry, bd_entry_ptr);
                pagefault_enable();
                if (!ret)
                        break;