Skip to content

Commit

Permalink
uprobes/x86: Fix RIP-relative handling of EVEX-encoded instructions
Browse files Browse the repository at this point in the history
Since instruction decoder now supports EVEX-encoded instructions, two fixes
are needed to correctly handle them in uprobes.

Extended bits for MODRM.rm field need to be sanitized just like we do it
for VEX3, to avoid encoding wrong register for register-relative access.

EVEX has _two_ extended bits: b and x. Theoretically, EVEX.x should be
ignored by the CPU (since GPRs go only up to 15, not 31), but let's be
paranoid here: proper encoding for register-relative access
should have EVEX.x = 1.

Secondly, we should fetch vex.vvvv for EVEX too.
This is now super easy because instruction decoder populates
vex_prefix.bytes[2] for all flavors of (e)vex encodings, even for VEX2.

Signed-off-by: Denys Vlasenko <[email protected]>
Acked-by: Masami Hiramatsu <[email protected]>
Acked-by: Srikar Dronamraju <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Jim Keniston <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Josh Poimboeuf <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Vince Weaver <[email protected]>
Cc: [email protected]
Cc: <[email protected]> # v4.1+
Fixes: 8a764a8 ("x86/asm/decoder: Create artificial 3rd byte for 2-byte VEX")
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
dvlasenk authored and Ingo Molnar committed Aug 12, 2016
1 parent db4a835 commit 6818787
Showing 1 changed file with 11 additions and 11 deletions.
22 changes: 11 additions & 11 deletions arch/x86/kernel/uprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,20 +357,22 @@ static void riprel_analyze(struct arch_uprobe *auprobe, struct insn *insn)
*cursor &= 0xfe;
}
/*
* Similar treatment for VEX3 prefix.
* TODO: add XOP/EVEX treatment when insn decoder supports them
* Similar treatment for VEX3/EVEX prefix.
* TODO: add XOP treatment when insn decoder supports them
*/
if (insn->vex_prefix.nbytes == 3) {
if (insn->vex_prefix.nbytes >= 3) {
/*
* vex2: c5 rvvvvLpp (has no b bit)
* vex3/xop: c4/8f rxbmmmmm wvvvvLpp
* evex: 62 rxbR00mm wvvvv1pp zllBVaaa
* (evex will need setting of both b and x since
* in non-sib encoding evex.x is 4th bit of MODRM.rm)
* Setting VEX3.b (setting because it has inverted meaning):
* Setting VEX3.b (setting because it has inverted meaning).
* Setting EVEX.x since (in non-SIB encoding) EVEX.x
* is the 4th bit of MODRM.rm, and needs the same treatment.
* For VEX3-encoded insns, VEX3.x value has no effect in
* non-SIB encoding, the change is superfluous but harmless.
*/
cursor = auprobe->insn + insn_offset_vex_prefix(insn) + 1;
*cursor |= 0x20;
*cursor |= 0x60;
}

/*
Expand Down Expand Up @@ -415,12 +417,10 @@ static void riprel_analyze(struct arch_uprobe *auprobe, struct insn *insn)

reg = MODRM_REG(insn); /* Fetch modrm.reg */
reg2 = 0xff; /* Fetch vex.vvvv */
if (insn->vex_prefix.nbytes == 2)
reg2 = insn->vex_prefix.bytes[1];
else if (insn->vex_prefix.nbytes == 3)
if (insn->vex_prefix.nbytes)
reg2 = insn->vex_prefix.bytes[2];
/*
* TODO: add XOP, EXEV vvvv reading.
* TODO: add XOP vvvv reading.
*
* vex.vvvv field is in bits 6-3, bits are inverted.
* But in 32-bit mode, high-order bit may be ignored.
Expand Down

0 comments on commit 6818787

Please sign in to comment.