linux-trace-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] kprobes: Fix issues related to optkprobe
@ 2023-02-16  3:42 Yang Jihong
  2023-02-16  3:42 ` [PATCH v2 1/2] x86/kprobes: Fix __recover_optprobed_insn check optimizing logic Yang Jihong
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Yang Jihong @ 2023-02-16  3:42 UTC (permalink / raw)
  To: tglx, mingo, bp, dave.hansen, x86, hpa, naveen.n.rao,
	anil.s.keshavamurthy, davem, mhiramat, ast, peterz, linux-kernel,
	linux-trace-kernel
  Cc: stable, yangjihong1

Fixed optkprobe issues, mainly related to the x86 architecture.

Yang Jihong (2):
  x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
  x86/kprobes: Fix arch_check_optimized_kprobe check within
    optimized_kprobe range

 arch/x86/kernel/kprobes/opt.c | 6 +++---
 include/linux/kprobes.h       | 2 ++
 kernel/kprobes.c              | 4 ++--
 3 files changed, 7 insertions(+), 5 deletions(-)

-- 

Changes since v1:
  - Remove patch1 since there is already a fix patch.
  - Add "cc stable" and modify comment for patch2.
  - Use "kprobe_disarmed" instead of "kprobe_disabled" for patch3.
  - Add fix commmit and "cc stable" for patch3.

2.30.GIT


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/2] x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
  2023-02-16  3:42 [PATCH v2 0/2] kprobes: Fix issues related to optkprobe Yang Jihong
@ 2023-02-16  3:42 ` Yang Jihong
  2023-02-16  3:42 ` [PATCH v2 2/2] x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe range Yang Jihong
  2023-02-16 14:12 ` [PATCH v2 0/2] kprobes: Fix issues related to optkprobe Masami Hiramatsu
  2 siblings, 0 replies; 4+ messages in thread
From: Yang Jihong @ 2023-02-16  3:42 UTC (permalink / raw)
  To: tglx, mingo, bp, dave.hansen, x86, hpa, naveen.n.rao,
	anil.s.keshavamurthy, davem, mhiramat, ast, peterz, linux-kernel,
	linux-trace-kernel
  Cc: stable, yangjihong1

Since the following commit:

  commit f66c0447cca1 ("kprobes: Set unoptimized flag after unoptimizing code")

modified the update timing of the KPROBE_FLAG_OPTIMIZED, a optimized_kprobe
may be in the optimizing or unoptimizing state when op.kp->flags
has KPROBE_FLAG_OPTIMIZED and op->list is not empty.

The __recover_optprobed_insn check logic is incorrect, a kprobe in the
unoptimizing state may be incorrectly determined as unoptimizing.
As a result, incorrect instructions are copied.

The optprobe_queued_unopt function needs to be exported for invoking in
arch directory.

Cc: stable@vger.kernel.org
Fixes: f66c0447cca1 ("kprobes: Set unoptimized flag after unoptimizing code")
Signed-off-by: Yang Jihong <yangjihong1@huawei.com>
---
 arch/x86/kernel/kprobes/opt.c | 4 ++--
 include/linux/kprobes.h       | 1 +
 kernel/kprobes.c              | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
index e57e07b0edb6..f406bfa9a8cd 100644
--- a/arch/x86/kernel/kprobes/opt.c
+++ b/arch/x86/kernel/kprobes/opt.c
@@ -46,8 +46,8 @@ unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
 		/* This function only handles jump-optimized kprobe */
 		if (kp && kprobe_optimized(kp)) {
 			op = container_of(kp, struct optimized_kprobe, kp);
-			/* If op->list is not empty, op is under optimizing */
-			if (list_empty(&op->list))
+			/* If op is optimized or under unoptimizing */
+			if (list_empty(&op->list) || optprobe_queued_unopt(op))
 				goto found;
 		}
 	}
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index a0b92be98984..ab39285f71a6 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -378,6 +378,7 @@ extern void opt_pre_handler(struct kprobe *p, struct pt_regs *regs);
 DEFINE_INSN_CACHE_OPS(optinsn);
 
 extern void wait_for_kprobe_optimizer(void);
+bool optprobe_queued_unopt(struct optimized_kprobe *op);
 #else /* !CONFIG_OPTPROBES */
 static inline void wait_for_kprobe_optimizer(void) { }
 #endif /* CONFIG_OPTPROBES */
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1c18ecf9f98b..90b0fac6efa0 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -662,7 +662,7 @@ void wait_for_kprobe_optimizer(void)
 	mutex_unlock(&kprobe_mutex);
 }
 
-static bool optprobe_queued_unopt(struct optimized_kprobe *op)
+bool optprobe_queued_unopt(struct optimized_kprobe *op)
 {
 	struct optimized_kprobe *_op;
 
-- 
2.30.GIT


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe range
  2023-02-16  3:42 [PATCH v2 0/2] kprobes: Fix issues related to optkprobe Yang Jihong
  2023-02-16  3:42 ` [PATCH v2 1/2] x86/kprobes: Fix __recover_optprobed_insn check optimizing logic Yang Jihong
@ 2023-02-16  3:42 ` Yang Jihong
  2023-02-16 14:12 ` [PATCH v2 0/2] kprobes: Fix issues related to optkprobe Masami Hiramatsu
  2 siblings, 0 replies; 4+ messages in thread
From: Yang Jihong @ 2023-02-16  3:42 UTC (permalink / raw)
  To: tglx, mingo, bp, dave.hansen, x86, hpa, naveen.n.rao,
	anil.s.keshavamurthy, davem, mhiramat, ast, peterz, linux-kernel,
	linux-trace-kernel
  Cc: stable, yangjihong1

When arch_prepare_optimized_kprobe calculating jump destination address,
it copies original instructions from jmp-optimized kprobe (see
__recover_optprobed_insn), and calculated based on length of original
instruction.

arch_check_optimized_kprobe does not check KPROBE_FLAG_OPTIMATED when
checking whether jmp-optimized kprobe exists.
As a result, setup_detour_execution may jump to a range that has been
overwritten by jump destination address, resulting in an inval opcode error.

For example, assume that register two kprobes whose addresses are
<func+9> and <func+11> in "func" function.
The original code of "func" function is as follows:

   0xffffffff816cb5e9 <+9>:     push   %r12
   0xffffffff816cb5eb <+11>:    xor    %r12d,%r12d
   0xffffffff816cb5ee <+14>:    test   %rdi,%rdi
   0xffffffff816cb5f1 <+17>:    setne  %r12b
   0xffffffff816cb5f5 <+21>:    push   %rbp

1.Register the kprobe for <func+11>, assume that is kp1, corresponding optimized_kprobe is op1.
  After the optimization, "func" code changes to:

   0xffffffff816cc079 <+9>:     push   %r12
   0xffffffff816cc07b <+11>:    jmp    0xffffffffa0210000
   0xffffffff816cc080 <+16>:    incl   0xf(%rcx)
   0xffffffff816cc083 <+19>:    xchg   %eax,%ebp
   0xffffffff816cc084 <+20>:    (bad)
   0xffffffff816cc085 <+21>:    push   %rbp

Now op1->flags == KPROBE_FLAG_OPTIMATED;

2. Register the kprobe for <func+9>, assume that is kp2, corresponding optimized_kprobe is op2.

register_kprobe(kp2)
  register_aggr_kprobe
    alloc_aggr_kprobe
      __prepare_optimized_kprobe
        arch_prepare_optimized_kprobe
          __recover_optprobed_insn    // copy original bytes from kp1->optinsn.copied_insn,
                                      // jump address = <func+14>

3. disable kp1:

disable_kprobe(kp1)
  __disable_kprobe
    ...
    if (p == orig_p || aggr_kprobe_disabled(orig_p)) {
      ret = disarm_kprobe(orig_p, true)       // add op1 in unoptimizing_list, not unoptimized
      orig_p->flags |= KPROBE_FLAG_DISABLED;  // op1->flags ==  KPROBE_FLAG_OPTIMATED | KPROBE_FLAG_DISABLED
    ...

4. unregister kp2
__unregister_kprobe_top
  ...
  if (!kprobe_disabled(ap) && !kprobes_all_disarmed) {
    optimize_kprobe(op)
      ...
      if (arch_check_optimized_kprobe(op) < 0) // because op1 has KPROBE_FLAG_DISABLED, here not return
        return;
      p->kp.flags |= KPROBE_FLAG_OPTIMIZED;   //  now op2 has KPROBE_FLAG_OPTIMIZED
  }

"func" code now is:

   0xffffffff816cc079 <+9>:     int3
   0xffffffff816cc07a <+10>:    push   %rsp
   0xffffffff816cc07b <+11>:    jmp    0xffffffffa0210000
   0xffffffff816cc080 <+16>:    incl   0xf(%rcx)
   0xffffffff816cc083 <+19>:    xchg   %eax,%ebp
   0xffffffff816cc084 <+20>:    (bad)
   0xffffffff816cc085 <+21>:    push   %rbp

5. if call "func", int3 handler call setup_detour_execution:

  if (p->flags & KPROBE_FLAG_OPTIMIZED) {
    ...
    regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
    ...
  }

The code for the destination address is

   0xffffffffa021072c:  push   %r12
   0xffffffffa021072e:  xor    %r12d,%r12d
   0xffffffffa0210731:  jmp    0xffffffff816cb5ee <func+14>

However, <func+14> is not a valid start instruction address. As a result, an error occurs.

Cc: stable@vger.kernel.org
Fixes: f66c0447cca1 ("kprobes: Set unoptimized flag after unoptimizing code")
Signed-off-by: Yang Jihong <yangjihong1@huawei.com>
---
 arch/x86/kernel/kprobes/opt.c | 2 +-
 include/linux/kprobes.h       | 1 +
 kernel/kprobes.c              | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
index f406bfa9a8cd..57b0037d0a99 100644
--- a/arch/x86/kernel/kprobes/opt.c
+++ b/arch/x86/kernel/kprobes/opt.c
@@ -353,7 +353,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe *op)
 
 	for (i = 1; i < op->optinsn.size; i++) {
 		p = get_kprobe(op->kp.addr + i);
-		if (p && !kprobe_disabled(p))
+		if (p && !kprobe_disarmed(p))
 			return -EEXIST;
 	}
 
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index ab39285f71a6..85a64cb95d75 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -379,6 +379,7 @@ DEFINE_INSN_CACHE_OPS(optinsn);
 
 extern void wait_for_kprobe_optimizer(void);
 bool optprobe_queued_unopt(struct optimized_kprobe *op);
+bool kprobe_disarmed(struct kprobe *p);
 #else /* !CONFIG_OPTPROBES */
 static inline void wait_for_kprobe_optimizer(void) { }
 #endif /* CONFIG_OPTPROBES */
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 90b0fac6efa0..99c3f4de3e5c 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -458,7 +458,7 @@ static inline int kprobe_optready(struct kprobe *p)
 }
 
 /* Return true if the kprobe is disarmed. Note: p must be on hash list */
-static inline bool kprobe_disarmed(struct kprobe *p)
+bool kprobe_disarmed(struct kprobe *p)
 {
 	struct optimized_kprobe *op;
 
-- 
2.30.GIT


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 0/2] kprobes: Fix issues related to optkprobe
  2023-02-16  3:42 [PATCH v2 0/2] kprobes: Fix issues related to optkprobe Yang Jihong
  2023-02-16  3:42 ` [PATCH v2 1/2] x86/kprobes: Fix __recover_optprobed_insn check optimizing logic Yang Jihong
  2023-02-16  3:42 ` [PATCH v2 2/2] x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe range Yang Jihong
@ 2023-02-16 14:12 ` Masami Hiramatsu
  2 siblings, 0 replies; 4+ messages in thread
From: Masami Hiramatsu @ 2023-02-16 14:12 UTC (permalink / raw)
  To: Yang Jihong
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, naveen.n.rao,
	anil.s.keshavamurthy, davem, ast, peterz, linux-kernel,
	linux-trace-kernel, stable

On Thu, 16 Feb 2023 11:42:45 +0800
Yang Jihong <yangjihong1@huawei.com> wrote:

> Fixed optkprobe issues, mainly related to the x86 architecture.
> 
> Yang Jihong (2):
>   x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
>   x86/kprobes: Fix arch_check_optimized_kprobe check within
>     optimized_kprobe range
> 
>  arch/x86/kernel/kprobes/opt.c | 6 +++---
>  include/linux/kprobes.h       | 2 ++
>  kernel/kprobes.c              | 4 ++--
>  3 files changed, 7 insertions(+), 5 deletions(-)

Thanks for updating! These look good to me! 

Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Thank you,


> 
> -- 
> 
> Changes since v1:
>   - Remove patch1 since there is already a fix patch.
>   - Add "cc stable" and modify comment for patch2.
>   - Use "kprobe_disarmed" instead of "kprobe_disabled" for patch3.
>   - Add fix commmit and "cc stable" for patch3.
> 
> 2.30.GIT
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-02-16 14:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-02-16  3:42 [PATCH v2 0/2] kprobes: Fix issues related to optkprobe Yang Jihong
2023-02-16  3:42 ` [PATCH v2 1/2] x86/kprobes: Fix __recover_optprobed_insn check optimizing logic Yang Jihong
2023-02-16  3:42 ` [PATCH v2 2/2] x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe range Yang Jihong
2023-02-16 14:12 ` [PATCH v2 0/2] kprobes: Fix issues related to optkprobe Masami Hiramatsu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).