3.19.8-ckt12 -stable review patch.  If anyone has any objections, please let me 
know.

------------------

From: Dave Hansen <dave.han...@linux.intel.com>

commit 54587653904c552c56b9dec153d7a89063394b09 upstream.

Currently, to get from a bounds directory entry to the virtual
address of a bounds table, we simply mask off a few low bits.
However, the set of bits we mask off is different for 32-bit and
64-bit binaries.

This breaks the operation out in to a helper function and also
adds a temporary variable to store the result until we are
sure we are returning one.

Signed-off-by: Dave Hansen <dave.han...@linux.intel.com>
Reviewed-by: Thomas Gleixner <t...@linutronix.de>
Cc: Andrew Morton <a...@linux-foundation.org>
Cc: Dave Hansen <d...@sr71.net>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/20150607183704.00768...@viggo.jf.intel.com
Signed-off-by: Ingo Molnar <mi...@kernel.org>
[ kamal: 3.19-stable prereq for "46561c3 x86/mpx: Do proper get_user() when
  running 32-bit binaries on 64-bit kernels" ]
Signed-off-by: Kamal Mostafa <ka...@canonical.com>
---
 arch/x86/include/asm/mpx.h |  1 -
 arch/x86/mm/mpx.c          | 41 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/mpx.h b/arch/x86/include/asm/mpx.h
index a952a13d..2857144 100644
--- a/arch/x86/include/asm/mpx.h
+++ b/arch/x86/include/asm/mpx.h
@@ -46,7 +46,6 @@
 #define MPX_BNDCFG_TAIL                12
 #define MPX_BNDSTA_ADDR_MASK   (~((1UL<<MPX_BNDSTA_TAIL)-1))
 #define MPX_BNDCFG_ADDR_MASK   (~((1UL<<MPX_BNDCFG_TAIL)-1))
-#define MPX_BT_ADDR_MASK       (~((1UL<<MPX_BD_ENTRY_TAIL)-1))
 
 #define MPX_BNDCFG_ADDR_MASK   (~((1UL<<MPX_BNDCFG_TAIL)-1))
 #define MPX_BNDSTA_ERROR_CODE  0x3
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index 9c208e4..1013f04 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -555,29 +555,55 @@ static int mpx_resolve_fault(long __user *addr, int write)
        return 0;
 }
 
+static unsigned long mpx_bd_entry_to_bt_addr(struct mm_struct *mm,
+                                            unsigned long bd_entry)
+{
+       unsigned long bt_addr = bd_entry;
+       int align_to_bytes;
+       /*
+        * Bit 0 in a bt_entry is always the valid bit.
+        */
+       bt_addr &= ~MPX_BD_ENTRY_VALID_FLAG;
+       /*
+        * Tables are naturally aligned at 8-byte boundaries
+        * on 64-bit and 4-byte boundaries on 32-bit.  The
+        * documentation makes it appear that the low bits
+        * are ignored by the hardware, so we do the same.
+        */
+       if (is_64bit_mm(mm))
+               align_to_bytes = 8;
+       else
+               align_to_bytes = 4;
+       bt_addr &= ~(align_to_bytes-1);
+       return bt_addr;
+}
+
 /*
  * Get the base of bounds tables pointed by specific bounds
  * directory entry.
  */
 static int get_bt_addr(struct mm_struct *mm,
-                       long __user *bd_entry, unsigned long *bt_addr)
+                       long __user *bd_entry_ptr,
+                       unsigned long *bt_addr_result)
 {
        int ret;
        int valid_bit;
+       unsigned long bd_entry;
+       unsigned long bt_addr;
 
-       if (!access_ok(VERIFY_READ, (bd_entry), sizeof(*bd_entry)))
+       if (!access_ok(VERIFY_READ, (bd_entry_ptr), sizeof(*bd_entry_ptr)))
                return -EFAULT;
 
        while (1) {
                int need_write = 0;
 
                pagefault_disable();
-               ret = get_user(*bt_addr, bd_entry);
+               ret = get_user(bd_entry, bd_entry_ptr);
                pagefault_enable();
                if (!ret)
                        break;
                if (ret == -EFAULT)
-                       ret = mpx_resolve_fault(bd_entry, need_write);
+                       ret = mpx_resolve_fault(bd_entry_ptr, need_write);
                /*
                 * If we could not resolve the fault, consider it
                 * userspace's fault and error out.
@@ -586,8 +612,8 @@ static int get_bt_addr(struct mm_struct *mm,
                        return ret;
        }
 
-       valid_bit = *bt_addr & MPX_BD_ENTRY_VALID_FLAG;
-       *bt_addr &= MPX_BT_ADDR_MASK;
+       valid_bit = bd_entry & MPX_BD_ENTRY_VALID_FLAG;
+       bt_addr = mpx_bd_entry_to_bt_addr(mm, bd_entry);
 
        /*
         * When the kernel is managing bounds tables, a bounds directory
@@ -596,7 +622,7 @@ static int get_bt_addr(struct mm_struct *mm,
         * data in the address field, we know something is wrong. This
         * -EINVAL return will cause a SIGSEGV.
         */
-       if (!valid_bit && *bt_addr)
+       if (!valid_bit && bt_addr)
                return -EINVAL;
        /*
         * Do we have an completely zeroed bt entry?  That is OK.  It
@@ -607,6 +633,7 @@ static int get_bt_addr(struct mm_struct *mm,
        if (!valid_bit)
                return -ENOENT;
 
+       *bt_addr_result = bt_addr;
        return 0;
 }
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to