aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/mpx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/mpx.c')
-rw-r--r--arch/x86/mm/mpx.c41
1 files changed, 34 insertions, 7 deletions
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
579static 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 */
583static int get_bt_addr(struct mm_struct *mm, 606static 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