Commit 8898f1ad authored by Dave Hansen's avatar Dave Hansen Committed by Kamal Mostafa

x86/mpx: Introduce new 'directory entry' to 'addr' helper function

commit 54587653 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: default avatarDave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Dave Hansen <dave@sr71.net>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150607183704.007686CE@viggo.jf.intel.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
[ kamal: 3.19-stable prereq for "46561c39 x86/mpx: Do proper get_user() when
  running 32-bit binaries on 64-bit kernels" ]
Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
parent 7d757760
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
#define MPX_BNDCFG_TAIL 12 #define MPX_BNDCFG_TAIL 12
#define MPX_BNDSTA_ADDR_MASK (~((1UL<<MPX_BNDSTA_TAIL)-1)) #define MPX_BNDSTA_ADDR_MASK (~((1UL<<MPX_BNDSTA_TAIL)-1))
#define MPX_BNDCFG_ADDR_MASK (~((1UL<<MPX_BNDCFG_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_BNDCFG_ADDR_MASK (~((1UL<<MPX_BNDCFG_TAIL)-1))
#define MPX_BNDSTA_ERROR_CODE 0x3 #define MPX_BNDSTA_ERROR_CODE 0x3
......
...@@ -555,29 +555,55 @@ static int mpx_resolve_fault(long __user *addr, int write) ...@@ -555,29 +555,55 @@ static int mpx_resolve_fault(long __user *addr, int write)
return 0; 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 * Get the base of bounds tables pointed by specific bounds
* directory entry. * directory entry.
*/ */
static int get_bt_addr(struct mm_struct *mm, 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 ret;
int valid_bit; 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; return -EFAULT;
while (1) { while (1) {
int need_write = 0; int need_write = 0;
pagefault_disable(); pagefault_disable();
ret = get_user(*bt_addr, bd_entry); ret = get_user(bd_entry, bd_entry_ptr);
pagefault_enable(); pagefault_enable();
if (!ret) if (!ret)
break; break;
if (ret == -EFAULT) 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 * If we could not resolve the fault, consider it
* userspace's fault and error out. * userspace's fault and error out.
...@@ -586,8 +612,8 @@ static int get_bt_addr(struct mm_struct *mm, ...@@ -586,8 +612,8 @@ static int get_bt_addr(struct mm_struct *mm,
return ret; return ret;
} }
valid_bit = *bt_addr & MPX_BD_ENTRY_VALID_FLAG; valid_bit = bd_entry & MPX_BD_ENTRY_VALID_FLAG;
*bt_addr &= MPX_BT_ADDR_MASK; bt_addr = mpx_bd_entry_to_bt_addr(mm, bd_entry);
/* /*
* When the kernel is managing bounds tables, a bounds directory * When the kernel is managing bounds tables, a bounds directory
...@@ -596,7 +622,7 @@ static int get_bt_addr(struct mm_struct *mm, ...@@ -596,7 +622,7 @@ static int get_bt_addr(struct mm_struct *mm,
* data in the address field, we know something is wrong. This * data in the address field, we know something is wrong. This
* -EINVAL return will cause a SIGSEGV. * -EINVAL return will cause a SIGSEGV.
*/ */
if (!valid_bit && *bt_addr) if (!valid_bit && bt_addr)
return -EINVAL; return -EINVAL;
/* /*
* Do we have an completely zeroed bt entry? That is OK. It * 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, ...@@ -607,6 +633,7 @@ static int get_bt_addr(struct mm_struct *mm,
if (!valid_bit) if (!valid_bit)
return -ENOENT; return -ENOENT;
*bt_addr_result = bt_addr;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment