diff options
author | Dave Hansen <dave.hansen@linux.intel.com> | 2015-06-07 14:37:04 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-06-09 06:24:33 -0400 |
commit | 54587653904c552c56b9dec153d7a89063394b09 (patch) | |
tree | 4de02a9b75978d004e1dd800c1d37be6f3d5c499 | |
parent | a1149fc83a1f97612e72ec24a0bdbabff7b85e77 (diff) |
x86/mpx: Introduce new 'directory entry' to 'addr' helper function
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.hansen@linux.intel.com>
Reviewed-by: Thomas 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.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/include/asm/mpx.h | 1 | ||||
-rw-r--r-- | 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 871e5e5b0499..99d374eb7b08 100644 --- a/arch/x86/include/asm/mpx.h +++ b/arch/x86/include/asm/mpx.h | |||
@@ -45,7 +45,6 @@ | |||
45 | #define MPX_BNDSTA_TAIL 2 | 45 | #define MPX_BNDSTA_TAIL 2 |
46 | #define MPX_BNDCFG_TAIL 12 | 46 | #define MPX_BNDCFG_TAIL 12 |
47 | #define MPX_BNDSTA_ADDR_MASK (~((1UL<<MPX_BNDSTA_TAIL)-1)) | 47 | #define MPX_BNDSTA_ADDR_MASK (~((1UL<<MPX_BNDSTA_TAIL)-1)) |
48 | #define MPX_BT_ADDR_MASK (~((1UL<<MPX_BD_ENTRY_TAIL)-1)) | ||
49 | 48 | ||
50 | #define MPX_BNDCFG_ADDR_MASK (~((1UL<<MPX_BNDCFG_TAIL)-1)) | 49 | #define MPX_BNDCFG_ADDR_MASK (~((1UL<<MPX_BNDCFG_TAIL)-1)) |
51 | #define MPX_BNDSTA_ERROR_CODE 0x3 | 50 | #define MPX_BNDSTA_ERROR_CODE 0x3 |
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c index 4f7fb7c233cc..8cc793479039 100644 --- a/arch/x86/mm/mpx.c +++ b/arch/x86/mm/mpx.c | |||
@@ -576,29 +576,55 @@ static int mpx_resolve_fault(long __user *addr, int write) | |||
576 | return 0; | 576 | return 0; |
577 | } | 577 | } |
578 | 578 | ||
579 | static unsigned long mpx_bd_entry_to_bt_addr(struct mm_struct *mm, | ||
580 | unsigned long bd_entry) | ||
581 | { | ||
582 | unsigned long bt_addr = bd_entry; | ||
583 | int align_to_bytes; | ||
584 | /* | ||
585 | * Bit 0 in a bt_entry is always the valid bit. | ||
586 | */ | ||
587 | bt_addr &= ~MPX_BD_ENTRY_VALID_FLAG; | ||
588 | /* | ||
589 | * Tables are naturally aligned at 8-byte boundaries | ||
590 | * on 64-bit and 4-byte boundaries on 32-bit. The | ||
591 | * documentation makes it appear that the low bits | ||
592 | * are ignored by the hardware, so we do the same. | ||
593 | */ | ||
594 | if (is_64bit_mm(mm)) | ||
595 | align_to_bytes = 8; | ||
596 | else | ||
597 | align_to_bytes = 4; | ||
598 | bt_addr &= ~(align_to_bytes-1); | ||
599 | return bt_addr; | ||
600 | } | ||
601 | |||
579 | /* | 602 | /* |
580 | * Get the base of bounds tables pointed by specific bounds | 603 | * Get the base of bounds tables pointed by specific bounds |
581 | * directory entry. | 604 | * directory entry. |
582 | */ | 605 | */ |
583 | static int get_bt_addr(struct mm_struct *mm, | 606 | static int get_bt_addr(struct mm_struct *mm, |
584 | long __user *bd_entry, unsigned long *bt_addr) | 607 | long __user *bd_entry_ptr, |
608 | unsigned long *bt_addr_result) | ||
585 | { | 609 | { |
586 | int ret; | 610 | int ret; |
587 | int valid_bit; | 611 | int valid_bit; |
612 | unsigned long bd_entry; | ||
613 | unsigned long bt_addr; | ||
588 | 614 | ||
589 | if (!access_ok(VERIFY_READ, (bd_entry), sizeof(*bd_entry))) | 615 | if (!access_ok(VERIFY_READ, (bd_entry_ptr), sizeof(*bd_entry_ptr))) |
590 | return -EFAULT; | 616 | return -EFAULT; |
591 | 617 | ||
592 | while (1) { | 618 | while (1) { |
593 | int need_write = 0; | 619 | int need_write = 0; |
594 | 620 | ||
595 | pagefault_disable(); | 621 | pagefault_disable(); |
596 | ret = get_user(*bt_addr, bd_entry); | 622 | ret = get_user(bd_entry, bd_entry_ptr); |
597 | pagefault_enable(); | 623 | pagefault_enable(); |
598 | if (!ret) | 624 | if (!ret) |
599 | break; | 625 | break; |
600 | if (ret == -EFAULT) | 626 | if (ret == -EFAULT) |
601 | ret = mpx_resolve_fault(bd_entry, need_write); | 627 | ret = mpx_resolve_fault(bd_entry_ptr, need_write); |
602 | /* | 628 | /* |
603 | * If we could not resolve the fault, consider it | 629 | * If we could not resolve the fault, consider it |
604 | * userspace's fault and error out. | 630 | * userspace's fault and error out. |
@@ -607,8 +633,8 @@ static int get_bt_addr(struct mm_struct *mm, | |||
607 | return ret; | 633 | return ret; |
608 | } | 634 | } |
609 | 635 | ||
610 | valid_bit = *bt_addr & MPX_BD_ENTRY_VALID_FLAG; | 636 | valid_bit = bd_entry & MPX_BD_ENTRY_VALID_FLAG; |
611 | *bt_addr &= MPX_BT_ADDR_MASK; | 637 | bt_addr = mpx_bd_entry_to_bt_addr(mm, bd_entry); |
612 | 638 | ||
613 | /* | 639 | /* |
614 | * When the kernel is managing bounds tables, a bounds directory | 640 | * When the kernel is managing bounds tables, a bounds directory |
@@ -617,7 +643,7 @@ static int get_bt_addr(struct mm_struct *mm, | |||
617 | * data in the address field, we know something is wrong. This | 643 | * data in the address field, we know something is wrong. This |
618 | * -EINVAL return will cause a SIGSEGV. | 644 | * -EINVAL return will cause a SIGSEGV. |
619 | */ | 645 | */ |
620 | if (!valid_bit && *bt_addr) | 646 | if (!valid_bit && bt_addr) |
621 | return -EINVAL; | 647 | return -EINVAL; |
622 | /* | 648 | /* |
623 | * Do we have an completely zeroed bt entry? That is OK. It | 649 | * Do we have an completely zeroed bt entry? That is OK. It |
@@ -628,6 +654,7 @@ static int get_bt_addr(struct mm_struct *mm, | |||
628 | if (!valid_bit) | 654 | if (!valid_bit) |
629 | return -ENOENT; | 655 | return -ENOENT; |
630 | 656 | ||
657 | *bt_addr_result = bt_addr; | ||
631 | return 0; | 658 | return 0; |
632 | } | 659 | } |
633 | 660 | ||