Re: [PATCH -tip v2] x86/kprobes: Do not decode opcode in resume_execution()

2021-01-04 Thread Borislav Petkov
On Mon, Jan 04, 2021 at 12:45:58PM +0900, Masami Hiramatsu wrote:
> Hrm, I meant setting the flags used in the resume_execution() afterwards.
> Since the instruction itself (not only opcode but also oprands) was
> also analyzed in other places, so I like the set_resume_flags() for it.

Your call but I still think that set_resume_flags() is misleading. You
even have in the comment above it:

"Analyze the opcode and set resume flags."

so it is doing some insn analysis and setting flags as a result.

But I won't insist - you're the one who's going to be staring at that
code.

:-)

-- 
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette


Re: [PATCH -tip v2] x86/kprobes: Do not decode opcode in resume_execution()

2021-01-03 Thread Masami Hiramatsu
On Thu, 31 Dec 2020 17:09:23 +0100
Borislav Petkov  wrote:

> On Fri, Dec 18, 2020 at 11:12:05PM +0900, Masami Hiramatsu wrote:
> > @@ -467,8 +489,8 @@ static int arch_copy_kprobe(struct kprobe *p)
> >  */
> > len = prepare_boost(buf, p, &insn);
> >  
> > -   /* Check whether the instruction modifies Interrupt Flag or not */
> > -   p->ainsn.if_modifier = is_IF_modifier(buf);
> > +   /* Analyze the opcode and set resume flags */
> > +   set_resume_flags(p, &insn);
> 
> So this function wants to be called something like analyze_insn() or so
> then? set_resume_flags() is kinda misleading as a name.

Hrm, I meant setting the flags used in the resume_execution() afterwards.
Since the instruction itself (not only opcode but also oprands) was
also analyzed in other places, so I like the set_resume_flags() for it.

Thank you,

-- 
Masami Hiramatsu 


Re: [PATCH -tip v2] x86/kprobes: Do not decode opcode in resume_execution()

2020-12-31 Thread Borislav Petkov
On Fri, Dec 18, 2020 at 11:12:05PM +0900, Masami Hiramatsu wrote:
> @@ -467,8 +489,8 @@ static int arch_copy_kprobe(struct kprobe *p)
>*/
>   len = prepare_boost(buf, p, &insn);
>  
> - /* Check whether the instruction modifies Interrupt Flag or not */
> - p->ainsn.if_modifier = is_IF_modifier(buf);
> + /* Analyze the opcode and set resume flags */
> + set_resume_flags(p, &insn);

So this function wants to be called something like analyze_insn() or so
then? set_resume_flags() is kinda misleading as a name.

Thx.

-- 
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette


[PATCH -tip v2] x86/kprobes: Do not decode opcode in resume_execution()

2020-12-18 Thread Masami Hiramatsu
Currently kprobes x86 decodes opcode right after single
stepping in resume_execution(). But it already decoded the
opcode while preparing arch_specific_insn in arch_copy_kprobe().

This decodes opcode in arch_copy_kprobe() instead of
resume_execution() and sets some flags which classifies
the opcode for resuming process.

Signed-off-by: Masami Hiramatsu 
Acked-by: Steven Rostedt (VMware) 
---
 Changes in v2:
  - Fix the timing of memset() for avoiding unexpected
cleanup of kprobe.ainsn.insn.
---
 arch/x86/include/asm/kprobes.h |   11 ++-
 arch/x86/kernel/kprobes/core.c |  167 ++--
 2 files changed, 81 insertions(+), 97 deletions(-)

diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index 991a7ad540c7..d20a3d6be36e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -58,14 +58,17 @@ struct arch_specific_insn {
/* copy of the original instruction */
kprobe_opcode_t *insn;
/*
-* boostable = false: This instruction type is not boostable.
-* boostable = true: This instruction has been boosted: we have
+* boostable = 0: This instruction type is not boostable.
+* boostable = 1: This instruction has been boosted: we have
 * added a relative jump after the instruction copy in insn,
 * so no single-step and fixup are needed (unless there's
 * a post_handler).
 */
-   bool boostable;
-   bool if_modifier;
+   unsigned boostable:1;
+   unsigned if_modifier:1;
+   unsigned is_call:1;
+   unsigned is_pushf:1;
+   unsigned is_abs_ip:1;
/* Number of bytes of text poked */
int tp_len;
 };
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 547c7abb39f5..01440e57961b 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -132,26 +132,6 @@ void synthesize_relcall(void *dest, void *from, void *to)
 }
 NOKPROBE_SYMBOL(synthesize_relcall);
 
-/*
- * Skip the prefixes of the instruction.
- */
-static kprobe_opcode_t *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 (inat_is_rex_prefix(attr))
-   insn++;
-#endif
-   return insn;
-}
-NOKPROBE_SYMBOL(skip_prefixes);
-
 /*
  * Returns non-zero if INSN is boostable.
  * RIP relative instructions are adjusted at copying time in 64 bits mode
@@ -311,25 +291,6 @@ static int can_probe(unsigned long paddr)
return (addr == paddr);
 }
 
-/*
- * Returns non-zero if opcode modifies the interrupt flag.
- */
-static int is_IF_modifier(kprobe_opcode_t *insn)
-{
-   /* Skip prefixes */
-   insn = skip_prefixes(insn);
-
-   switch (*insn) {
-   case 0xfa:  /* cli */
-   case 0xfb:  /* sti */
-   case 0xcf:  /* iret/iretd */
-   case 0x9d:  /* popf/popfd */
-   return 1;
-   }
-
-   return 0;
-}
-
 /*
  * Copy an instruction with recovering modified instruction by kprobes
  * and adjust the displacement if the instruction uses the %rip-relative
@@ -411,9 +372,9 @@ static int prepare_boost(kprobe_opcode_t *buf, struct 
kprobe *p,
synthesize_reljump(buf + len, p->ainsn.insn + len,
   p->addr + insn->length);
len += JMP32_INSN_SIZE;
-   p->ainsn.boostable = true;
+   p->ainsn.boostable = 1;
} else {
-   p->ainsn.boostable = false;
+   p->ainsn.boostable = 0;
}
 
return len;
@@ -450,6 +411,67 @@ void free_insn_page(void *page)
module_memfree(page);
 }
 
+static void set_resume_flags(struct kprobe *p, struct insn *insn)
+{
+   insn_byte_t opcode = insn->opcode.bytes[0];
+
+   switch (opcode) {
+   case 0xfa:  /* cli */
+   case 0xfb:  /* sti */
+   case 0x9d:  /* popf/popfd */
+   /* Check whether the instruction modifies Interrupt Flag or not 
*/
+   p->ainsn.if_modifier = 1;
+   break;
+   case 0x9c:  /* pushfl */
+   p->ainsn.is_pushf = 1;
+   break;
+   case 0xcf:  /* iret */
+   p->ainsn.if_modifier = 1;
+   fallthrough;
+   case 0xc2:  /* ret/lret */
+   case 0xc3:
+   case 0xca:
+   case 0xcb:
+   case 0xea:  /* jmp absolute -- ip is correct */
+   /* ip is already adjusted, no more changes required */
+   p->ainsn.is_abs_ip = 1;
+   /* Without resume jump, this is boostable */
+   p->ainsn.boostable = 1;
+   break;
+   case 0xe8:  /* call relati