Commit 4578f06f authored by Ricardo Neri's avatar Ricardo Neri Committed by Thomas Gleixner

x86/mpx: Do not use SIB.base if its value is 101b and ModRM.mod = 0

Section 2.2.1.2 of the Intel 64 and IA-32 Architectures Software
Developer's Manual volume 2A states that if a SIB byte is used and
SIB.base is 101b and ModRM.mod is zero, then the base part of the base
part of the effective address computation is null. To signal this
situation, a -EDOM error is returned to indicate callers to ignore the
base value present in the register operand.

In this scenario, a 32-bit displacement follows the SIB byte. Displacement
is obtained when the instruction decoder parses the operands.
Signed-off-by: default avatarRicardo Neri <ricardo.neri-calderon@linux.intel.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarBorislav Petkov <bp@suse.de>
Cc: Adan Hawthorn <adanhawthorn@gmail.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: ricardo.neri@intel.com
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Nathan Howard <liverlint@gmail.com>
Cc: "Ravi V. Shankar" <ravi.v.shankar@intel.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Joe Perches <joe@perches.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Link: https://lkml.kernel.org/r/1509135945-13762-9-git-send-email-ricardo.neri-calderon@linux.intel.com
parent ff9d7802
...@@ -123,6 +123,14 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs, ...@@ -123,6 +123,14 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
case REG_TYPE_BASE: case REG_TYPE_BASE:
regno = X86_SIB_BASE(insn->sib.value); regno = X86_SIB_BASE(insn->sib.value);
/*
* If ModRM.mod is 0 and SIB.base == 5, the base of the
* register-indirect addressing is 0. In this case, a
* 32-bit displacement follows the SIB byte.
*/
if (!X86_MODRM_MOD(insn->modrm.value) && regno == 5)
return -EDOM;
if (X86_REX_B(insn->rex_prefix.value)) if (X86_REX_B(insn->rex_prefix.value))
regno += 8; regno += 8;
break; break;
...@@ -164,16 +172,22 @@ static void __user *mpx_get_addr_ref(struct insn *insn, struct pt_regs *regs) ...@@ -164,16 +172,22 @@ static void __user *mpx_get_addr_ref(struct insn *insn, struct pt_regs *regs)
eff_addr = regs_get_register(regs, addr_offset); eff_addr = regs_get_register(regs, addr_offset);
} else { } else {
if (insn->sib.nbytes) { if (insn->sib.nbytes) {
/*
* Negative values in the base and index offset means
* an error when decoding the SIB byte. Except -EDOM,
* which means that the registers should not be used
* in the address computation.
*/
base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE); base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE);
if (base_offset < 0) if (base_offset == -EDOM)
base = 0;
else if (base_offset < 0)
goto out; goto out;
else
base = regs_get_register(regs, base_offset);
indx_offset = get_reg_offset(insn, regs, REG_TYPE_INDEX); indx_offset = get_reg_offset(insn, regs, REG_TYPE_INDEX);
/*
* A negative offset generally means a error, except
* -EDOM, which means that the contents of the register
* should not be used as index.
*/
if (indx_offset == -EDOM) if (indx_offset == -EDOM)
indx = 0; indx = 0;
else if (indx_offset < 0) else if (indx_offset < 0)
...@@ -181,8 +195,6 @@ static void __user *mpx_get_addr_ref(struct insn *insn, struct pt_regs *regs) ...@@ -181,8 +195,6 @@ static void __user *mpx_get_addr_ref(struct insn *insn, struct pt_regs *regs)
else else
indx = regs_get_register(regs, indx_offset); indx = regs_get_register(regs, indx_offset);
base = regs_get_register(regs, base_offset);
eff_addr = base + indx * (1 << X86_SIB_SCALE(sib)); eff_addr = base + indx * (1 << X86_SIB_SCALE(sib));
} else { } else {
addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM); addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment