/* * When a BNDSTX instruction attempts to save bounds to a bounds * table, it will first attempt to look up the table in the * first-level bounds directory. If it does not find a table in * the directory, a #BR is generated and we get here in order to * allocate a new table. * * With 32-bit mode, the size of BD is 4MB, and the size of each * bound table is 16KB. With 64-bit mode, the size of BD is 2GB, * and the size of each bound table is 4MB. */ static int do_mpx_bt_fault(void) { unsigned long bd_entry, bd_base; const struct bndcsr *bndcsr; struct mm_struct *mm = current->mm; bndcsr = get_xsave_field_ptr(XSTATE_BNDCSR); if (!bndcsr) return -EINVAL; /* * Mask off the preserve and enable bits */ bd_base = bndcsr->bndcfgu & MPX_BNDCFG_ADDR_MASK; /* * The hardware provides the address of the missing or invalid * entry via BNDSTATUS, so we don't have to go look it up. */ bd_entry = bndcsr->bndstatus & MPX_BNDSTA_ADDR_MASK; /* * Make sure the directory entry is within where we think * the directory is. */ if ((bd_entry < bd_base) || (bd_entry >= bd_base + mpx_bd_size_bytes(mm))) return -EINVAL; return allocate_bt(mm, (long __user *)bd_entry); }
static __user void *mpx_get_bounds_dir(void) { const struct bndcsr *bndcsr; if (!cpu_feature_enabled(X86_FEATURE_MPX)) return MPX_INVALID_BOUNDS_DIR; /* * The bounds directory pointer is stored in a register * only accessible if we first do an xsave. */ bndcsr = get_xsave_field_ptr(XSTATE_BNDCSR); if (!bndcsr) return MPX_INVALID_BOUNDS_DIR; /* * Make sure the register looks valid by checking the * enable bit. */ if (!(bndcsr->bndcfgu & MPX_BNDCFG_ENABLE_FLAG)) return MPX_INVALID_BOUNDS_DIR; /* * Lastly, mask off the low bits used for configuration * flags, and return the address of the bounds table. */ return (void __user *)(unsigned long) (bndcsr->bndcfgu & MPX_BNDCFG_ADDR_MASK); }
/* * If a bounds overflow occurs then a #BR is generated. This * function decodes MPX instructions to get violation address * and set this address into extended struct siginfo. * * Note that this is not a super precise way of doing this. * Userspace could have, by the time we get here, written * anything it wants in to the instructions. We can not * trust anything about it. They might not be valid * instructions or might encode invalid registers, etc... */ int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs) { const struct mpx_bndreg_state *bndregs; const struct mpx_bndreg *bndreg; struct insn insn; uint8_t bndregno; int err; err = mpx_insn_decode(&insn, regs); if (err) goto err_out; /* * We know at this point that we are only dealing with * MPX instructions. */ insn_get_modrm(&insn); bndregno = X86_MODRM_REG(insn.modrm.value); if (bndregno > 3) { err = -EINVAL; goto err_out; } /* get bndregs field from current task's xsave area */ bndregs = get_xsave_field_ptr(XFEATURE_MASK_BNDREGS); if (!bndregs) { err = -EINVAL; goto err_out; } /* now go select the individual register in the set of 4 */ bndreg = &bndregs->bndreg[bndregno]; /* * The registers are always 64-bit, but the upper 32 * bits are ignored in 32-bit mode. Also, note that the * upper bounds are architecturally represented in 1's * complement form. * * The 'unsigned long' cast is because the compiler * complains when casting from integers to different-size * pointers. */ info->lower = (void __user *)(unsigned long)bndreg->lower_bound; info->upper = (void __user *)(unsigned long)~bndreg->upper_bound; info->addr = insn_get_addr_ref(&insn, regs); /* * We were not able to extract an address from the instruction, * probably because there was something invalid in it. */ if (info->addr == (void __user *)-1) { err = -EINVAL; goto err_out; } trace_mpx_bounds_register_exception(info->addr, bndreg); return 0; err_out: /* info might be NULL, but kfree() handles that */ return err; }
/* * If a bounds overflow occurs then a #BR is generated. This * function decodes MPX instructions to get violation address * and set this address into extended struct siginfo. * * Note that this is not a super precise way of doing this. * Userspace could have, by the time we get here, written * anything it wants in to the instructions. We can not * trust anything about it. They might not be valid * instructions or might encode invalid registers, etc... * * The caller is expected to kfree() the returned siginfo_t. */ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs) { const struct bndreg *bndregs, *bndreg; siginfo_t *info = NULL; struct insn insn; uint8_t bndregno; int err; err = mpx_insn_decode(&insn, regs); if (err) goto err_out; /* * We know at this point that we are only dealing with * MPX instructions. */ insn_get_modrm(&insn); bndregno = X86_MODRM_REG(insn.modrm.value); if (bndregno > 3) { err = -EINVAL; goto err_out; } /* get bndregs field from current task's xsave area */ bndregs = get_xsave_field_ptr(XSTATE_BNDREGS); if (!bndregs) { err = -EINVAL; goto err_out; } /* now go select the individual register in the set of 4 */ bndreg = &bndregs[bndregno]; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { err = -ENOMEM; goto err_out; } /* * The registers are always 64-bit, but the upper 32 * bits are ignored in 32-bit mode. Also, note that the * upper bounds are architecturally represented in 1's * complement form. * * The 'unsigned long' cast is because the compiler * complains when casting from integers to different-size * pointers. */ info->si_lower = (void __user *)(unsigned long)bndreg->lower_bound; info->si_upper = (void __user *)(unsigned long)~bndreg->upper_bound; info->si_addr_lsb = 0; info->si_signo = SIGSEGV; info->si_errno = 0; info->si_code = SEGV_BNDERR; info->si_addr = mpx_get_addr_ref(&insn, regs); /* * We were not able to extract an address from the instruction, * probably because there was something invalid in it. */ if (info->si_addr == (void *)-1) { err = -EINVAL; goto err_out; } trace_mpx_bounds_register_exception(info->si_addr, bndreg); return info; err_out: /* info might be NULL, but kfree() handles that */ kfree(info); return ERR_PTR(err); }