|
@@ -126,16 +126,22 @@ static void __kprobes synthesize_reljump(void *from, void *to)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Check for the REX prefix which can only exist on X86_64
|
|
|
- * X86_32 always returns 0
|
|
|
+ * Skip the prefixes of the instruction.
|
|
|
*/
|
|
|
-static int __kprobes is_REX_prefix(kprobe_opcode_t *insn)
|
|
|
+static kprobe_opcode_t *__kprobes skip_prefixes(kprobe_opcode_t *insn)
|
|
|
{
|
|
|
+ insn_attr_t attr;
|
|
|
+
|
|
|
+ attr = inat_get_opcode_attribute((insn_byte_t)*insn);
|
|
|
+ while (inat_is_legacy_prefix(attr)) {
|
|
|
+ insn++;
|
|
|
+ attr = inat_get_opcode_attribute((insn_byte_t)*insn);
|
|
|
+ }
|
|
|
#ifdef CONFIG_X86_64
|
|
|
- if ((*insn & 0xf0) == 0x40)
|
|
|
- return 1;
|
|
|
+ if (inat_is_rex_prefix(attr))
|
|
|
+ insn++;
|
|
|
#endif
|
|
|
- return 0;
|
|
|
+ return insn;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -272,6 +278,9 @@ static int __kprobes can_probe(unsigned long paddr)
|
|
|
*/
|
|
|
static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
|
|
|
{
|
|
|
+ /* Skip prefixes */
|
|
|
+ insn = skip_prefixes(insn);
|
|
|
+
|
|
|
switch (*insn) {
|
|
|
case 0xfa: /* cli */
|
|
|
case 0xfb: /* sti */
|
|
@@ -280,13 +289,6 @@ static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * on X86_64, 0x40-0x4f are REX prefixes so we need to look
|
|
|
- * at the next byte instead.. but of course not recurse infinitely
|
|
|
- */
|
|
|
- if (is_REX_prefix(insn))
|
|
|
- return is_IF_modifier(++insn);
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -803,9 +805,8 @@ static void __kprobes resume_execution(struct kprobe *p,
|
|
|
unsigned long orig_ip = (unsigned long)p->addr;
|
|
|
kprobe_opcode_t *insn = p->ainsn.insn;
|
|
|
|
|
|
- /*skip the REX prefix*/
|
|
|
- if (is_REX_prefix(insn))
|
|
|
- insn++;
|
|
|
+ /* Skip prefixes */
|
|
|
+ insn = skip_prefixes(insn);
|
|
|
|
|
|
regs->flags &= ~X86_EFLAGS_TF;
|
|
|
switch (*insn) {
|