Merge branch 'x86/mpx' into x86/asm, to pick up dependent commits
The UMIP series is based on top of changes already queued up in the x86/mpx branch, so merge it. Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include <linux/sched/sysctl.h>
|
||||
|
||||
#include <asm/insn.h>
|
||||
#include <asm/insn-eval.h>
|
||||
#include <asm/mman.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/mpx.h>
|
||||
@@ -61,123 +62,6 @@ static unsigned long mpx_mmap(unsigned long len)
|
||||
return addr;
|
||||
}
|
||||
|
||||
enum reg_type {
|
||||
REG_TYPE_RM = 0,
|
||||
REG_TYPE_INDEX,
|
||||
REG_TYPE_BASE,
|
||||
};
|
||||
|
||||
static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
|
||||
enum reg_type type)
|
||||
{
|
||||
int regno = 0;
|
||||
|
||||
static const int regoff[] = {
|
||||
offsetof(struct pt_regs, ax),
|
||||
offsetof(struct pt_regs, cx),
|
||||
offsetof(struct pt_regs, dx),
|
||||
offsetof(struct pt_regs, bx),
|
||||
offsetof(struct pt_regs, sp),
|
||||
offsetof(struct pt_regs, bp),
|
||||
offsetof(struct pt_regs, si),
|
||||
offsetof(struct pt_regs, di),
|
||||
#ifdef CONFIG_X86_64
|
||||
offsetof(struct pt_regs, r8),
|
||||
offsetof(struct pt_regs, r9),
|
||||
offsetof(struct pt_regs, r10),
|
||||
offsetof(struct pt_regs, r11),
|
||||
offsetof(struct pt_regs, r12),
|
||||
offsetof(struct pt_regs, r13),
|
||||
offsetof(struct pt_regs, r14),
|
||||
offsetof(struct pt_regs, r15),
|
||||
#endif
|
||||
};
|
||||
int nr_registers = ARRAY_SIZE(regoff);
|
||||
/*
|
||||
* Don't possibly decode a 32-bit instructions as
|
||||
* reading a 64-bit-only register.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_X86_64) && !insn->x86_64)
|
||||
nr_registers -= 8;
|
||||
|
||||
switch (type) {
|
||||
case REG_TYPE_RM:
|
||||
regno = X86_MODRM_RM(insn->modrm.value);
|
||||
if (X86_REX_B(insn->rex_prefix.value))
|
||||
regno += 8;
|
||||
break;
|
||||
|
||||
case REG_TYPE_INDEX:
|
||||
regno = X86_SIB_INDEX(insn->sib.value);
|
||||
if (X86_REX_X(insn->rex_prefix.value))
|
||||
regno += 8;
|
||||
break;
|
||||
|
||||
case REG_TYPE_BASE:
|
||||
regno = X86_SIB_BASE(insn->sib.value);
|
||||
if (X86_REX_B(insn->rex_prefix.value))
|
||||
regno += 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("invalid register type");
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
if (regno >= nr_registers) {
|
||||
WARN_ONCE(1, "decoded an instruction with an invalid register");
|
||||
return -EINVAL;
|
||||
}
|
||||
return regoff[regno];
|
||||
}
|
||||
|
||||
/*
|
||||
* return the address being referenced be instruction
|
||||
* for rm=3 returning the content of the rm reg
|
||||
* for rm!=3 calculates the address using SIB and Disp
|
||||
*/
|
||||
static void __user *mpx_get_addr_ref(struct insn *insn, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long addr, base, indx;
|
||||
int addr_offset, base_offset, indx_offset;
|
||||
insn_byte_t sib;
|
||||
|
||||
insn_get_modrm(insn);
|
||||
insn_get_sib(insn);
|
||||
sib = insn->sib.value;
|
||||
|
||||
if (X86_MODRM_MOD(insn->modrm.value) == 3) {
|
||||
addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
|
||||
if (addr_offset < 0)
|
||||
goto out_err;
|
||||
addr = regs_get_register(regs, addr_offset);
|
||||
} else {
|
||||
if (insn->sib.nbytes) {
|
||||
base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE);
|
||||
if (base_offset < 0)
|
||||
goto out_err;
|
||||
|
||||
indx_offset = get_reg_offset(insn, regs, REG_TYPE_INDEX);
|
||||
if (indx_offset < 0)
|
||||
goto out_err;
|
||||
|
||||
base = regs_get_register(regs, base_offset);
|
||||
indx = regs_get_register(regs, indx_offset);
|
||||
addr = base + indx * (1 << X86_SIB_SCALE(sib));
|
||||
} else {
|
||||
addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
|
||||
if (addr_offset < 0)
|
||||
goto out_err;
|
||||
addr = regs_get_register(regs, addr_offset);
|
||||
}
|
||||
addr += insn->displacement.value;
|
||||
}
|
||||
return (void __user *)addr;
|
||||
out_err:
|
||||
return (void __user *)-1;
|
||||
}
|
||||
|
||||
static int mpx_insn_decode(struct insn *insn,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
@@ -290,7 +174,7 @@ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs)
|
||||
info->si_signo = SIGSEGV;
|
||||
info->si_errno = 0;
|
||||
info->si_code = SEGV_BNDERR;
|
||||
info->si_addr = mpx_get_addr_ref(&insn, regs);
|
||||
info->si_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.
|
||||
|
Reference in New Issue
Block a user