Commit-ID: e526a302e425ab11111efc5f59e52449bbcc768e Gitweb: https://git.kernel.org/tip/e526a302e425ab11111efc5f59e52449bbcc768e Author: Ricardo Neri <[email protected]> AuthorDate: Fri, 27 Oct 2017 13:25:44 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 1 Nov 2017 21:50:13 +0100
x86/insn-eval: Indicate a 32-bit displacement if ModRM.mod is 0 and ModRM.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-calde...@linux.intel.com --- arch/x86/lib/insn-eval.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c index 01e36bd..6bf819f 100644 --- a/arch/x86/lib/insn-eval.c +++ b/arch/x86/lib/insn-eval.c @@ -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; @@ -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;

