Skip to content

Commit

Permalink
x86/insn-eval: Indicate a 32-bit displacement if ModRM.mod is 0 and M…
Browse files Browse the repository at this point in the history
…odRM.rm is 101b

Section 2.2.1.3 of the Intel 64 and IA-32 Architectures Software
Developer's Manual volume 2A states that when ModRM.mod is zero and
ModRM.rm is 101b, a 32-bit displacement follows the ModRM byte. This means
that none of the registers are used in the computation of the effective
address. A return value of -EDOM indicates callers that they should not
use the value of registers when computing the effective address for the
instruction.

In long mode, the effective address is given by the 32-bit displacement
plus the location of the next instruction. In protected mode, only the
displacement is used.

The instruction decoder takes care of obtaining the displacement.

Signed-off-by: Ricardo Neri <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Reviewed-by: Borislav Petkov <[email protected]>
Cc: "Michael S. Tsirkin" <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: [email protected]
Cc: Adrian Hunter <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Huang Rui <[email protected]>
Cc: Qiaowei Ren <[email protected]>
Cc: Shuah Khan <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Cc: Jiri Slaby <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: "Ravi V. Shankar" <[email protected]>
Cc: Chris Metcalf <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Colin Ian King <[email protected]>
Cc: Chen Yucong <[email protected]>
Cc: Adam Buchbinder <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Cc: Lorenzo Stoakes <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Thomas Garnier <[email protected]>
Link: https://lkml.kernel.org/r/1509135945-13762-18-git-send-email-ricardo.neri-calderon@linux.intel.com
  • Loading branch information
ricardon authored and KAGA-KOKO committed Nov 1, 2017
1 parent 4efea85 commit e526a30
Showing 1 changed file with 22 additions and 3 deletions.
25 changes: 22 additions & 3 deletions arch/x86/lib/insn-eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,14 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
switch (type) {
case REG_TYPE_RM:
regno = X86_MODRM_RM(insn->modrm.value);

/*
* ModRM.mod == 0 and ModRM.rm == 5 means a 32-bit displacement
* follows the ModRM byte.
*/
if (!X86_MODRM_MOD(insn->modrm.value) && regno == 5)
return -EDOM;

if (X86_REX_B(insn->rex_prefix.value))
regno += 8;
break;
Expand Down Expand Up @@ -770,10 +778,21 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
eff_addr = base + indx * (1 << X86_SIB_SCALE(sib));
} else {
addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
if (addr_offset < 0)
/*
* -EDOM means that we must ignore the address_offset.
* In such a case, in 64-bit mode the effective address
* relative to the RIP of the following instruction.
*/
if (addr_offset == -EDOM) {
if (user_64bit_mode(regs))
eff_addr = (long)regs->ip + insn->length;
else
eff_addr = 0;
} else if (addr_offset < 0) {
goto out;

eff_addr = regs_get_register(regs, addr_offset);
} else {
eff_addr = regs_get_register(regs, addr_offset);
}
}

eff_addr += insn->displacement.value;
Expand Down

0 comments on commit e526a30

Please sign in to comment.