Lines Matching +full:start +full:- +full:up
1 // SPDX-License-Identifier: GPL-2.0
3 * mpx.c - Memory Protection eXtensions
16 #include <asm/insn-eval.h>
44 * bounds tables (the bounds directory is user-allocated).
48 struct mm_struct *mm = current->mm; in mpx_mmap()
53 return -EINVAL; in mpx_mmap()
55 down_write(&mm->mmap_sem); in mpx_mmap()
58 up_write(&mm->mmap_sem); in mpx_mmap()
73 not_copied = copy_from_user(buf, (void __user *)regs->ip, sizeof(buf)); in mpx_insn_decode()
74 nr_copied = sizeof(buf) - not_copied; in mpx_insn_decode()
81 return -EFAULT; in mpx_insn_decode()
92 if (nr_copied < insn->length) in mpx_insn_decode()
93 return -EFAULT; in mpx_insn_decode()
100 if (insn->opcode.bytes[0] != 0x0f) in mpx_insn_decode()
102 if ((insn->opcode.bytes[1] != 0x1a) && in mpx_insn_decode()
103 (insn->opcode.bytes[1] != 0x1b)) in mpx_insn_decode()
108 return -EINVAL; in mpx_insn_decode()
144 err = -EINVAL; in mpx_generate_siginfo()
150 err = -EINVAL; in mpx_generate_siginfo()
154 bndreg = &bndregs->bndreg[bndregno]; in mpx_generate_siginfo()
158 err = -ENOMEM; in mpx_generate_siginfo()
162 * The registers are always 64-bit, but the upper 32 in mpx_generate_siginfo()
163 * bits are ignored in 32-bit mode. Also, note that the in mpx_generate_siginfo()
168 * complains when casting from integers to different-size in mpx_generate_siginfo()
171 info->si_lower = (void __user *)(unsigned long)bndreg->lower_bound; in mpx_generate_siginfo()
172 info->si_upper = (void __user *)(unsigned long)~bndreg->upper_bound; in mpx_generate_siginfo()
173 info->si_addr_lsb = 0; in mpx_generate_siginfo()
174 info->si_signo = SIGSEGV; in mpx_generate_siginfo()
175 info->si_errno = 0; in mpx_generate_siginfo()
176 info->si_code = SEGV_BNDERR; in mpx_generate_siginfo()
177 info->si_addr = insn_get_addr_ref(&insn, regs); in mpx_generate_siginfo()
182 if (info->si_addr == (void __user *)-1) { in mpx_generate_siginfo()
183 err = -EINVAL; in mpx_generate_siginfo()
186 trace_mpx_bounds_register_exception(info->si_addr, bndreg); in mpx_generate_siginfo()
213 if (!(bndcsr->bndcfgu & MPX_BNDCFG_ENABLE_FLAG)) in mpx_get_bounds_dir()
221 (bndcsr->bndcfgu & MPX_BNDCFG_ADDR_MASK); in mpx_get_bounds_dir()
227 struct mm_struct *mm = current->mm; in mpx_enable_management()
239 * unmap path; we can just use mm->context.bd_addr instead. in mpx_enable_management()
242 down_write(&mm->mmap_sem); in mpx_enable_management()
247 "above 47-bits. Disabling.", in mpx_enable_management()
248 current->comm, current->pid); in mpx_enable_management()
249 ret = -ENXIO; in mpx_enable_management()
252 mm->context.bd_addr = bd_base; in mpx_enable_management()
253 if (mm->context.bd_addr == MPX_INVALID_BOUNDS_DIR) in mpx_enable_management()
254 ret = -ENXIO; in mpx_enable_management()
256 up_write(&mm->mmap_sem); in mpx_enable_management()
262 struct mm_struct *mm = current->mm; in mpx_disable_management()
265 return -ENXIO; in mpx_disable_management()
267 down_write(&mm->mmap_sem); in mpx_disable_management()
268 mm->context.bd_addr = MPX_INVALID_BOUNDS_DIR; in mpx_disable_management()
269 up_write(&mm->mmap_sem); in mpx_disable_management()
283 * pass a pointer to a 64-bit data type when we only want in mpx_cmpxchg_bd_entry()
284 * a 32-bit copy. in mpx_cmpxchg_bd_entry()
303 * With 32-bit mode, a bounds directory is 4MB, and the size of each
304 * bounds table is 16KB. With 64-bit mode, a bounds directory is 2GB,
358 * We found a non-empty bd_entry but it did not have the in allocate_bt()
364 ret = -EINVAL; in allocate_bt()
376 * table, it will first attempt to look up the table in the
377 * first-level bounds directory. If it does not find a table in
381 * With 32-bit mode, the size of BD is 4MB, and the size of each
382 * bound table is 16KB. With 64-bit mode, the size of BD is 2GB,
389 struct mm_struct *mm = current->mm; in do_mpx_bt_fault()
393 return -EINVAL; in do_mpx_bt_fault()
397 bd_base = bndcsr->bndcfgu & MPX_BNDCFG_ADDR_MASK; in do_mpx_bt_fault()
400 * entry via BNDSTATUS, so we don't have to go look it up. in do_mpx_bt_fault()
402 bd_entry = bndcsr->bndstatus & MPX_BNDSTA_ADDR_MASK; in do_mpx_bt_fault()
409 return -EINVAL; in do_mpx_bt_fault()
420 if (!kernel_managing_mpx_tables(current->mm)) in mpx_handle_bd_fault()
421 return -EINVAL; in mpx_handle_bd_fault()
428 * fault was resolved or -errno if not.
443 return -EFAULT; in mpx_resolve_fault()
461 * Tables are naturally aligned at 8-byte boundaries in mpx_bd_entry_to_bt_addr()
462 * on 64-bit and 4-byte boundaries on 32-bit. The in mpx_bd_entry_to_bt_addr()
470 bt_addr &= ~(align_to_bytes-1); in mpx_bd_entry_to_bt_addr()
475 * We only want to do a 4-byte get_user() on 32-bit. Otherwise,
477 * a 64-bit kernel and try to get 8 bytes.
511 return -EFAULT; in get_bt_addr()
521 if (ret == -EFAULT) in get_bt_addr()
539 * -EINVAL return will cause a SIGSEGV. in get_bt_addr()
542 return -EINVAL; in get_bt_addr()
546 * sure to distinguish this from -EINVAL, which will cause in get_bt_addr()
550 return -ENOENT; in get_bt_addr()
576 /* Bottom 3 bits are ignored on 64-bit */ in mpx_get_bt_entry_offset_bytes()
580 /* Bottom 2 bits are ignored on 32-bit */ in mpx_get_bt_entry_offset_bytes()
594 offset &= (bt_table_nr_entries-1); in mpx_get_bt_entry_offset_bytes()
597 * the table. We need to scale it back up to bytes. in mpx_get_bt_entry_offset_bytes()
608 * to a long on 32-bit.
616 * This covers 32-bit emulation as well as 32-bit kernels in bd_entry_virt_space()
617 * running on 64-bit hardware. in bd_entry_virt_space()
624 * of, and returns the full >32-bit address space when in bd_entry_virt_space()
625 * running 32-bit kernels on 64-bit hardware. in bd_entry_virt_space()
633 * Assume start...end is within that bounds table.
641 unsigned long start; in zap_bt_entries_mapping() local
646 * is not what we want. Back it up a byte to get the in zap_bt_entries_mapping()
648 * move 'end' back up by the table entry size. in zap_bt_entries_mapping()
650 start = bt_addr + mpx_get_bt_entry_offset_bytes(mm, start_mapping); in zap_bt_entries_mapping()
651 end = bt_addr + mpx_get_bt_entry_offset_bytes(mm, end_mapping - 1); in zap_bt_entries_mapping()
653 * Move end back up by one entry. Among other things in zap_bt_entries_mapping()
654 * this ensures that it remains page-aligned and does in zap_bt_entries_mapping()
655 * not screw up zap_page_range() in zap_bt_entries_mapping()
660 * Find the first overlapping vma. If vma->vm_start > start, there in zap_bt_entries_mapping()
661 * will be a hole in the bounds table. This -EINVAL return will in zap_bt_entries_mapping()
664 vma = find_vma(mm, start); in zap_bt_entries_mapping()
665 if (!vma || vma->vm_start > start) in zap_bt_entries_mapping()
666 return -EINVAL; in zap_bt_entries_mapping()
670 * be split. So we need to look across the entire 'start -> end' in zap_bt_entries_mapping()
674 addr = start; in zap_bt_entries_mapping()
675 while (vma && vma->vm_start < end) { in zap_bt_entries_mapping()
678 * here. If we find a non-MPX VMA, that's bad, in zap_bt_entries_mapping()
682 if (!(vma->vm_flags & VM_MPX)) in zap_bt_entries_mapping()
683 return -EINVAL; in zap_bt_entries_mapping()
685 len = min(vma->vm_end, end) - addr; in zap_bt_entries_mapping()
689 vma = vma->vm_next; in zap_bt_entries_mapping()
690 addr = vma->vm_start; in zap_bt_entries_mapping()
710 int bd_entry_size = 8; /* 64-bit pointer */ in mpx_get_bd_entry_offset()
712 * Take the 64-bit addressing hole in to account. in mpx_get_bd_entry_offset()
714 addr &= ((1UL << boot_cpu_data.x86_virt_bits) - 1); in mpx_get_bd_entry_offset()
717 int bd_entry_size = 4; /* 32-bit pointer */ in mpx_get_bd_entry_offset()
719 * 32-bit has no hole so this case needs no mask in mpx_get_bd_entry_offset()
726 * realize that we're doing a power-of-2 divide and use in mpx_get_bd_entry_offset()
727 * shifts. It uses a real divide. If we put them up in mpx_get_bd_entry_offset()
749 if (ret == -EFAULT) in unmap_entire_bt()
774 * wrong, so pass up the error and SIGSEGV. in unmap_entire_bt()
776 return -EINVAL; in unmap_entire_bt()
787 unsigned long start, unsigned long end) in try_unmap_single_bt() argument
795 unsigned long bta_start_vaddr = start & ~(bd_entry_virt_space(mm)-1); in try_unmap_single_bt()
801 * We already unlinked the VMAs from the mm's rbtree so 'start' in try_unmap_single_bt()
806 next = find_vma_prev(mm, start, &prev); in try_unmap_single_bt()
811 * If we count them as neighbors here, we may end up with in try_unmap_single_bt()
815 while (next && (next->vm_flags & VM_MPX)) in try_unmap_single_bt()
816 next = next->vm_next; in try_unmap_single_bt()
817 while (prev && (prev->vm_flags & VM_MPX)) in try_unmap_single_bt()
818 prev = prev->vm_prev; in try_unmap_single_bt()
820 * We know 'start' and 'end' lie within an area controlled in try_unmap_single_bt()
826 next = find_vma_prev(mm, start, &prev); in try_unmap_single_bt()
827 if ((!prev || prev->vm_end <= bta_start_vaddr) && in try_unmap_single_bt()
828 (!next || next->vm_start >= bta_end_vaddr)) { in try_unmap_single_bt()
833 start = bta_start_vaddr; in try_unmap_single_bt()
837 bde_vaddr = mm->context.bd_addr + mpx_get_bd_entry_offset(mm, start); in try_unmap_single_bt()
842 if (ret == -ENOENT) { in try_unmap_single_bt()
854 if ((start == bta_start_vaddr) && in try_unmap_single_bt()
857 return zap_bt_entries_mapping(mm, bt_addr, start, end); in try_unmap_single_bt()
861 unsigned long start, unsigned long end) in mpx_unmap_tables() argument
864 trace_mpx_unmap_search(start, end); in mpx_unmap_tables()
866 one_unmap_start = start; in mpx_unmap_tables()
890 * munmap()ed. Assume end > start.
893 * the virtual address region start...end have already been split if
894 * necessary, and the 'vma' is the first vma in this range (start -> end).
897 unsigned long start, unsigned long end) in mpx_notify_unmap() argument
905 if (!kernel_managing_mpx_tables(current->mm)) in mpx_notify_unmap()
908 * This will look across the entire 'start -> end' range, in mpx_notify_unmap()
909 * and find all of the non-VM_MPX VMAs. in mpx_notify_unmap()
912 * (start->end), we will not continue follow-up work. This in mpx_notify_unmap()
918 if (vma->vm_flags & VM_MPX) in mpx_notify_unmap()
920 vma = vma->vm_next; in mpx_notify_unmap()
921 } while (vma && vma->vm_start < end); in mpx_notify_unmap()
923 ret = mpx_unmap_tables(mm, start, end); in mpx_notify_unmap()
932 if (!kernel_managing_mpx_tables(current->mm)) in mpx_unmapped_area_check()
937 return -ENOMEM; in mpx_unmapped_area_check()
941 * Resetting hinting address wouldn't do much good -- fail early. in mpx_unmapped_area_check()
944 return -ENOMEM; in mpx_unmapped_area_check()