Skip to content

Commit 89ae465

Browse files
Masami Hiramatsufweisbec
authored andcommitted
kprobes: Cleanup fix_riprel() using insn decoder on x86
Cleanup fix_riprel() in arch/x86/kernel/kprobes.c by using the new x86 instruction decoder instead of using comparisons with raw ad hoc numeric opcodes. Signed-off-by: Masami Hiramatsu <[email protected]> Cc: Ananth N Mavinakayanahalli <[email protected]> Cc: Avi Kivity <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Frank Ch. Eigler <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jason Baron <[email protected]> Cc: Jim Keniston <[email protected]> Cc: K.Prasad <[email protected]> Cc: Lai Jiangshan <[email protected]> Cc: Li Zefan <[email protected]> Cc: Przemysław Pawełczyk <[email protected]> Cc: Roland McGrath <[email protected]> Cc: Sam Ravnborg <[email protected]> Cc: Srikar Dronamraju <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Tom Zanussi <[email protected]> Cc: Vegard Nossum <[email protected]> LKML-Reference: <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]>
1 parent b46b3d7 commit 89ae465

File tree

1 file changed

+23
-105
lines changed

1 file changed

+23
-105
lines changed

arch/x86/kernel/kprobes.c

Lines changed: 23 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -108,50 +108,6 @@ static const u32 twobyte_is_boostable[256 / 32] = {
108108
/* ----------------------------------------------- */
109109
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
110110
};
111-
static const u32 onebyte_has_modrm[256 / 32] = {
112-
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
113-
/* ----------------------------------------------- */
114-
W(0x00, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 00 */
115-
W(0x10, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) , /* 10 */
116-
W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 20 */
117-
W(0x30, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) , /* 30 */
118-
W(0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 40 */
119-
W(0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 50 */
120-
W(0x60, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0) | /* 60 */
121-
W(0x70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 70 */
122-
W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */
123-
W(0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 90 */
124-
W(0xa0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* a0 */
125-
W(0xb0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* b0 */
126-
W(0xc0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0) | /* c0 */
127-
W(0xd0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
128-
W(0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* e0 */
129-
W(0xf0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) /* f0 */
130-
/* ----------------------------------------------- */
131-
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
132-
};
133-
static const u32 twobyte_has_modrm[256 / 32] = {
134-
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
135-
/* ----------------------------------------------- */
136-
W(0x00, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1) | /* 0f */
137-
W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0) , /* 1f */
138-
W(0x20, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* 2f */
139-
W(0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 3f */
140-
W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 4f */
141-
W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 5f */
142-
W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 6f */
143-
W(0x70, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1) , /* 7f */
144-
W(0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 8f */
145-
W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 9f */
146-
W(0xa0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1) | /* af */
147-
W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1) , /* bf */
148-
W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0) | /* cf */
149-
W(0xd0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* df */
150-
W(0xe0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* ef */
151-
W(0xf0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0) /* ff */
152-
/* ----------------------------------------------- */
153-
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
154-
};
155111
#undef W
156112

157113
struct kretprobe_blackpoint kretprobe_blacklist[] = {
@@ -348,68 +304,30 @@ static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
348304
static void __kprobes fix_riprel(struct kprobe *p)
349305
{
350306
#ifdef CONFIG_X86_64
351-
u8 *insn = p->ainsn.insn;
352-
s64 disp;
353-
int need_modrm;
354-
355-
/* Skip legacy instruction prefixes. */
356-
while (1) {
357-
switch (*insn) {
358-
case 0x66:
359-
case 0x67:
360-
case 0x2e:
361-
case 0x3e:
362-
case 0x26:
363-
case 0x64:
364-
case 0x65:
365-
case 0x36:
366-
case 0xf0:
367-
case 0xf3:
368-
case 0xf2:
369-
++insn;
370-
continue;
371-
}
372-
break;
373-
}
307+
struct insn insn;
308+
kernel_insn_init(&insn, p->ainsn.insn);
374309

375-
/* Skip REX instruction prefix. */
376-
if (is_REX_prefix(insn))
377-
++insn;
378-
379-
if (*insn == 0x0f) {
380-
/* Two-byte opcode. */
381-
++insn;
382-
need_modrm = test_bit(*insn,
383-
(unsigned long *)twobyte_has_modrm);
384-
} else
385-
/* One-byte opcode. */
386-
need_modrm = test_bit(*insn,
387-
(unsigned long *)onebyte_has_modrm);
388-
389-
if (need_modrm) {
390-
u8 modrm = *++insn;
391-
if ((modrm & 0xc7) == 0x05) {
392-
/* %rip+disp32 addressing mode */
393-
/* Displacement follows ModRM byte. */
394-
++insn;
395-
/*
396-
* The copied instruction uses the %rip-relative
397-
* addressing mode. Adjust the displacement for the
398-
* difference between the original location of this
399-
* instruction and the location of the copy that will
400-
* actually be run. The tricky bit here is making sure
401-
* that the sign extension happens correctly in this
402-
* calculation, since we need a signed 32-bit result to
403-
* be sign-extended to 64 bits when it's added to the
404-
* %rip value and yield the same 64-bit result that the
405-
* sign-extension of the original signed 32-bit
406-
* displacement would have given.
407-
*/
408-
disp = (u8 *) p->addr + *((s32 *) insn) -
409-
(u8 *) p->ainsn.insn;
410-
BUG_ON((s64) (s32) disp != disp); /* Sanity check. */
411-
*(s32 *)insn = (s32) disp;
412-
}
310+
if (insn_rip_relative(&insn)) {
311+
s64 newdisp;
312+
u8 *disp;
313+
insn_get_displacement(&insn);
314+
/*
315+
* The copied instruction uses the %rip-relative addressing
316+
* mode. Adjust the displacement for the difference between
317+
* the original location of this instruction and the location
318+
* of the copy that will actually be run. The tricky bit here
319+
* is making sure that the sign extension happens correctly in
320+
* this calculation, since we need a signed 32-bit result to
321+
* be sign-extended to 64 bits when it's added to the %rip
322+
* value and yield the same 64-bit result that the sign-
323+
* extension of the original signed 32-bit displacement would
324+
* have given.
325+
*/
326+
newdisp = (u8 *) p->addr + (s64) insn.displacement.value -
327+
(u8 *) p->ainsn.insn;
328+
BUG_ON((s64) (s32) newdisp != newdisp); /* Sanity check. */
329+
disp = (u8 *) p->ainsn.insn + insn_offset_displacement(&insn);
330+
*(s32 *) disp = (s32) newdisp;
413331
}
414332
#endif
415333
}

0 commit comments

Comments
 (0)