All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers
@ 2020-08-27 16:38 Masami Hiramatsu
  2020-08-27 16:38 ` [PATCH v3 01/16] kprobes: Add generic kretprobe trampoline handler Masami Hiramatsu
                   ` (15 more replies)
  0 siblings, 16 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:38 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Hi,

Here is the 3rd version of the series to unify the kretprobe trampoline handler
implementation across all architectures which are currently kprobes supported.
Previous version is here;

 https://lkml.kernel.org/r/159852811819.707944.12798182250041968537.stgit@devnote2

This series removes the in_nmi() check from pre_kretprobe_handler() since we
can avoid double-lock deadlock from NMI by kprobe_busy_begin/end() and use
kfree_rcu() to release kretprobe_instance. Also, cleanup local functions to
static symbols.

Thank you,

---

Masami Hiramatsu (16):
      kprobes: Add generic kretprobe trampoline handler
      x86/kprobes: Use generic kretprobe trampoline handler
      arm: kprobes: Use generic kretprobe trampoline handler
      arm64: kprobes: Use generic kretprobe trampoline handler
      arc: kprobes: Use generic kretprobe trampoline handler
      csky: kprobes: Use generic kretprobe trampoline handler
      ia64: kprobes: Use generic kretprobe trampoline handler
      mips: kprobes: Use generic kretprobe trampoline handler
      parisc: kprobes: Use generic kretprobe trampoline handler
      powerpc: kprobes: Use generic kretprobe trampoline handler
      s390: kprobes: Use generic kretprobe trampoline handler
      sh: kprobes: Use generic kretprobe trampoline handler
      sparc: kprobes: Use generic kretprobe trampoline handler
      kprobes: Remove NMI context check
      kprobes: Free kretprobe_instance with rcu callback
      kprobes: Make local used functions static


 arch/arc/kernel/kprobes.c          |   55 +--------------
 arch/arm/probes/kprobes/core.c     |   79 +--------------------
 arch/arm64/kernel/probes/kprobes.c |   79 +--------------------
 arch/csky/kernel/probes/kprobes.c  |   78 +--------------------
 arch/ia64/kernel/kprobes.c         |   79 +--------------------
 arch/mips/kernel/kprobes.c         |   55 +--------------
 arch/parisc/kernel/kprobes.c       |   78 ++-------------------
 arch/powerpc/kernel/kprobes.c      |   55 +--------------
 arch/s390/kernel/kprobes.c         |   81 +--------------------
 arch/sh/kernel/kprobes.c           |   59 +---------------
 arch/sparc/kernel/kprobes.c        |   52 +-------------
 arch/x86/kernel/kprobes/core.c     |  109 +----------------------------
 include/linux/kprobes.h            |   51 ++++++++------
 kernel/kprobes.c                   |  136 +++++++++++++++++++++++++++++-------
 14 files changed, 190 insertions(+), 856 deletions(-)

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

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

* [PATCH v3 01/16] kprobes: Add generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
@ 2020-08-27 16:38 ` Masami Hiramatsu
  2020-08-28  1:57   ` Masami Hiramatsu
  2020-08-27 16:38 ` [PATCH v3 02/16] x86/kprobes: Use " Masami Hiramatsu
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:38 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Add a generic kretprobe trampoline handler for unifying
the all cloned /arch/* kretprobe trampoline handlers.

The generic kretprobe trampoline handler is based on the
x86 implementation, because it is the latest implementation.
It has frame pointer checking, kprobe_busy_begin/end and
return address fixup for user handlers.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 include/linux/kprobes.h |   32 +++++++++++++--
 kernel/kprobes.c        |  101 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+), 4 deletions(-)

diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 9be1bff4f586..46a7afcf5ec0 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -187,10 +187,38 @@ static inline int kprobes_built_in(void)
 	return 1;
 }
 
+extern struct kprobe kprobe_busy;
+void kprobe_busy_begin(void);
+void kprobe_busy_end(void);
+
 #ifdef CONFIG_KRETPROBES
 extern void arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				   struct pt_regs *regs);
 extern int arch_trampoline_kprobe(struct kprobe *p);
+
+/* If the trampoline handler called from a kprobe, use this version */
+unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
+				unsigned long trampoline_address,
+				void *frame_pointer);
+
+static nokprobe_inline
+unsigned long kretprobe_trampoline_handler(struct pt_regs *regs,
+				unsigned long trampoline_address,
+				void *frame_pointer)
+{
+	unsigned long ret;
+	/*
+	 * Set a dummy kprobe for avoiding kretprobe recursion.
+	 * Since kretprobe never runs in kprobe handler, any kprobe must not
+	 * be running at this point.
+	 */
+	kprobe_busy_begin();
+	ret = __kretprobe_trampoline_handler(regs, trampoline_address, frame_pointer);
+	kprobe_busy_end();
+
+	return ret;
+}
+
 #else /* CONFIG_KRETPROBES */
 static inline void arch_prepare_kretprobe(struct kretprobe *rp,
 					struct pt_regs *regs)
@@ -354,10 +382,6 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
 	return this_cpu_ptr(&kprobe_ctlblk);
 }
 
-extern struct kprobe kprobe_busy;
-void kprobe_busy_begin(void);
-void kprobe_busy_end(void);
-
 kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset);
 int register_kprobe(struct kprobe *p);
 void unregister_kprobe(struct kprobe *p);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 287b263c9cb9..cbd2ad1af7b7 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1927,6 +1927,107 @@ unsigned long __weak arch_deref_entry_point(void *entry)
 }
 
 #ifdef CONFIG_KRETPROBES
+
+unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
+					unsigned long trampoline_address,
+					void *frame_pointer)
+{
+	struct kretprobe_instance *ri = NULL;
+	struct hlist_head *head, empty_rp;
+	struct hlist_node *tmp;
+	unsigned long flags, orig_ret_address = 0;
+	kprobe_opcode_t *correct_ret_addr = NULL;
+	bool skipped = false;
+
+	INIT_HLIST_HEAD(&empty_rp);
+	kretprobe_hash_lock(current, &head, &flags);
+
+	/*
+	 * It is possible to have multiple instances associated with a given
+	 * task either because multiple functions in the call path have
+	 * return probes installed on them, and/or more than one
+	 * return probe was registered for a target function.
+	 *
+	 * We can handle this because:
+	 *     - instances are always pushed into the head of the list
+	 *     - when multiple return probes are registered for the same
+	 *	 function, the (chronologically) first instance's ret_addr
+	 *	 will be the real return address, and all the rest will
+	 *	 point to kretprobe_trampoline.
+	 */
+	hlist_for_each_entry(ri, head, hlist) {
+		if (ri->task != current)
+			/* another task is sharing our hash bucket */
+			continue;
+		/*
+		 * Return probes must be pushed on this hash list correct
+		 * order (same as return order) so that it can be popped
+		 * correctly. However, if we find it is pushed it incorrect
+		 * order, this means we find a function which should not be
+		 * probed, because the wrong order entry is pushed on the
+		 * path of processing other kretprobe itself.
+		 */
+		if (ri->fp != frame_pointer) {
+			if (!skipped)
+				pr_warn("kretprobe is stacked incorrectly. Trying to fixup.\n");
+			skipped = true;
+			continue;
+		}
+
+		orig_ret_address = (unsigned long)ri->ret_addr;
+		if (skipped)
+			pr_warn("%ps must be blacklisted because of incorrect kretprobe order\n",
+				ri->rp->kp.addr);
+
+		if (orig_ret_address != trampoline_address)
+			/*
+			 * This is the real return address. Any other
+			 * instances associated with this task are for
+			 * other calls deeper on the call stack
+			 */
+			break;
+	}
+
+	kretprobe_assert(ri, orig_ret_address, trampoline_address);
+
+	correct_ret_addr = ri->ret_addr;
+	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
+		if (ri->task != current)
+			/* another task is sharing our hash bucket */
+			continue;
+		if (ri->fp != frame_pointer)
+			continue;
+
+		orig_ret_address = (unsigned long)ri->ret_addr;
+		if (ri->rp && ri->rp->handler) {
+			__this_cpu_write(current_kprobe, &ri->rp->kp);
+			ri->ret_addr = correct_ret_addr;
+			ri->rp->handler(ri, regs);
+			__this_cpu_write(current_kprobe, &kprobe_busy);
+		}
+
+		recycle_rp_inst(ri, &empty_rp);
+
+		if (orig_ret_address != trampoline_address)
+			/*
+			 * This is the real return address. Any other
+			 * instances associated with this task are for
+			 * other calls deeper on the call stack
+			 */
+			break;
+	}
+
+	kretprobe_hash_unlock(current, &flags);
+
+	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
+		hlist_del(&ri->hlist);
+		kfree(ri);
+	}
+
+	return orig_ret_address;
+}
+NOKPROBE_SYMBOL(__kretprobe_trampoline_handler)
+
 /*
  * This kprobe pre_handler is registered with every kretprobe. When probe
  * hits it will set up the return probe.


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

* [PATCH v3 02/16] x86/kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
  2020-08-27 16:38 ` [PATCH v3 01/16] kprobes: Add generic kretprobe trampoline handler Masami Hiramatsu
@ 2020-08-27 16:38 ` Masami Hiramatsu
  2020-08-27 16:39 ` [PATCH v3 03/16] arm: kprobes: " Masami Hiramatsu
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:38 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/x86/kernel/kprobes/core.c |  109 +---------------------------------------
 1 file changed, 4 insertions(+), 105 deletions(-)

diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index fdadc37d72af..7c6473a12cee 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -767,124 +767,23 @@ asm(
 NOKPROBE_SYMBOL(kretprobe_trampoline);
 STACK_FRAME_NON_STANDARD(kretprobe_trampoline);
 
+
 /*
  * Called from kretprobe_trampoline
  */
 __used __visible void *trampoline_handler(struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
-	kprobe_opcode_t *correct_ret_addr = NULL;
-	void *frame_pointer;
-	bool skipped = false;
-
-	/*
-	 * Set a dummy kprobe for avoiding kretprobe recursion.
-	 * Since kretprobe never run in kprobe handler, kprobe must not
-	 * be running at this point.
-	 */
-	kprobe_busy_begin();
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
 	/* fixup registers */
 	regs->cs = __KERNEL_CS;
 #ifdef CONFIG_X86_32
 	regs->cs |= get_kernel_rpl();
 	regs->gs = 0;
 #endif
-	/* We use pt_regs->sp for return address holder. */
-	frame_pointer = &regs->sp;
-	regs->ip = trampoline_address;
+	regs->ip = (unsigned long)&kretprobe_trampoline;
 	regs->orig_ax = ~0UL;
 
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because multiple functions in the call path have
-	 * return probes installed on them, and/or more than one
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always pushed into the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *	 function, the (chronologically) first instance's ret_addr
-	 *	 will be the real return address, and all the rest will
-	 *	 point to kretprobe_trampoline.
-	 */
-	hlist_for_each_entry(ri, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-		/*
-		 * Return probes must be pushed on this hash list correct
-		 * order (same as return order) so that it can be popped
-		 * correctly. However, if we find it is pushed it incorrect
-		 * order, this means we find a function which should not be
-		 * probed, because the wrong order entry is pushed on the
-		 * path of processing other kretprobe itself.
-		 */
-		if (ri->fp != frame_pointer) {
-			if (!skipped)
-				pr_warn("kretprobe is stacked incorrectly. Trying to fixup.\n");
-			skipped = true;
-			continue;
-		}
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		if (skipped)
-			pr_warn("%ps must be blacklisted because of incorrect kretprobe order\n",
-				ri->rp->kp.addr);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-	correct_ret_addr = ri->ret_addr;
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-		if (ri->fp != frame_pointer)
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		if (ri->rp && ri->rp->handler) {
-			__this_cpu_write(current_kprobe, &ri->rp->kp);
-			ri->ret_addr = correct_ret_addr;
-			ri->rp->handler(ri, regs);
-			__this_cpu_write(current_kprobe, &kprobe_busy);
-		}
-
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_hash_unlock(current, &flags);
-
-	kprobe_busy_end();
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
-	return (void *)orig_ret_address;
+	return (void *)kretprobe_trampoline_handler(regs,
+			(unsigned long)&kretprobe_trampoline, &regs->sp);
 }
 NOKPROBE_SYMBOL(trampoline_handler);
 


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

* [PATCH v3 03/16] arm: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
  2020-08-27 16:38 ` [PATCH v3 01/16] kprobes: Add generic kretprobe trampoline handler Masami Hiramatsu
  2020-08-27 16:38 ` [PATCH v3 02/16] x86/kprobes: Use " Masami Hiramatsu
@ 2020-08-27 16:39 ` Masami Hiramatsu
  2020-08-27 16:39 ` [PATCH v3 04/16] arm64: " Masami Hiramatsu
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:39 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Use the generic kretprobe trampoline handler. Use regs->ARM_fp
for framepointer verification.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
  Changes in v2:
   - Fix to cast frame_pointer type to void *.
---
 arch/arm/probes/kprobes/core.c |   79 ++--------------------------------------
 1 file changed, 4 insertions(+), 75 deletions(-)

diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c
index feefa2055eba..292d18975348 100644
--- a/arch/arm/probes/kprobes/core.c
+++ b/arch/arm/probes/kprobes/core.c
@@ -413,87 +413,16 @@ void __naked __kprobes kretprobe_trampoline(void)
 /* Called from kretprobe_trampoline */
 static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
-	kprobe_opcode_t *correct_ret_addr = NULL;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because multiple functions in the call path have
-	 * a return probe installed on them, and/or more than one return
-	 * probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *       function, the first instance's ret_addr will point to the
-	 *       real return address, and all the rest will point to
-	 *       kretprobe_trampoline
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-	correct_ret_addr = ri->ret_addr;
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		if (ri->rp && ri->rp->handler) {
-			__this_cpu_write(current_kprobe, &ri->rp->kp);
-			get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
-			ri->ret_addr = correct_ret_addr;
-			ri->rp->handler(ri, regs);
-			__this_cpu_write(current_kprobe, NULL);
-		}
-
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
-
-	return (void *)orig_ret_address;
+	return (void *)kretprobe_trampoline_handler(regs,
+				(unsigned long)&kretprobe_trampoline,
+				(void *)regs->ARM_fp);
 }
 
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr;
+	ri->fp = (void *)regs->ARM_fp;
 
 	/* Replace the return addr with trampoline addr. */
 	regs->ARM_lr = (unsigned long)&kretprobe_trampoline;


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

* [PATCH v3 04/16] arm64: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (2 preceding siblings ...)
  2020-08-27 16:39 ` [PATCH v3 03/16] arm: kprobes: " Masami Hiramatsu
@ 2020-08-27 16:39 ` Masami Hiramatsu
  2020-08-27 16:39 ` [PATCH v3 05/16] arc: " Masami Hiramatsu
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:39 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Use the generic kretprobe trampoline handler, and use the
kernel_stack_pointer(regs) for framepointer verification.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/arm64/kernel/probes/kprobes.c |   79 ++----------------------------------
 1 file changed, 4 insertions(+), 75 deletions(-)

diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 5290f17a4d80..1e4768001039 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -464,87 +464,16 @@ int __init arch_populate_kprobe_blacklist(void)
 
 void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address =
-		(unsigned long)&kretprobe_trampoline;
-	kprobe_opcode_t *correct_ret_addr = NULL;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because multiple functions in the call path have
-	 * return probes installed on them, and/or more than one
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always pushed into the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *	 function, the (chronologically) first instance's ret_addr
-	 *	 will be the real return address, and all the rest will
-	 *	 point to kretprobe_trampoline.
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-	correct_ret_addr = ri->ret_addr;
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		if (ri->rp && ri->rp->handler) {
-			__this_cpu_write(current_kprobe, &ri->rp->kp);
-			get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
-			ri->ret_addr = correct_ret_addr;
-			ri->rp->handler(ri, regs);
-			__this_cpu_write(current_kprobe, NULL);
-		}
-
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
-	return (void *)orig_ret_address;
+	return (void *)kretprobe_trampoline_handler(regs,
+				(unsigned long)&kretprobe_trampoline,
+				(void *)kernel_stack_pointer(regs));
 }
 
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *)regs->regs[30];
+	ri->fp = (void *)kernel_stack_pointer(regs);
 
 	/* replace return addr (x30) with trampoline */
 	regs->regs[30] = (long)&kretprobe_trampoline;


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

* [PATCH v3 05/16] arc: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (3 preceding siblings ...)
  2020-08-27 16:39 ` [PATCH v3 04/16] arm64: " Masami Hiramatsu
@ 2020-08-27 16:39 ` Masami Hiramatsu
  2020-08-27 16:39 ` [PATCH v3 06/16] csky: " Masami Hiramatsu
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:39 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/arc/kernel/kprobes.c |   55 ++-------------------------------------------
 1 file changed, 3 insertions(+), 52 deletions(-)

diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c
index 7d3efe83cba7..da615684240b 100644
--- a/arch/arc/kernel/kprobes.c
+++ b/arch/arc/kernel/kprobes.c
@@ -388,6 +388,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 {
 
 	ri->ret_addr = (kprobe_opcode_t *) regs->blink;
+	ri->fp = NULL;
 
 	/* Replace the return addr with trampoline addr */
 	regs->blink = (unsigned long)&kretprobe_trampoline;
@@ -396,58 +397,8 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 static int __kprobes trampoline_probe_handler(struct kprobe *p,
 					      struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because an multiple functions in the call path
-	 * have a return probe installed on them, and/or more than one return
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *       function, the first instance's ret_addr will point to the
-	 *       real return address, and all the rest will point to
-	 *       kretprobe_trampoline
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		if (ri->rp && ri->rp->handler)
-			ri->rp->handler(ri, regs);
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address) {
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-		}
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-	regs->ret = orig_ret_address;
-
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
+	regs->ret = __kretprobe_trampoline_handler(regs,
+				(unsigned long)&kretprobe_trampoline, NULL);
 
 	/* By returning a non zero value, we are telling the kprobe handler
 	 * that we don't want the post_handler to run


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

* [PATCH v3 06/16] csky: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (4 preceding siblings ...)
  2020-08-27 16:39 ` [PATCH v3 05/16] arc: " Masami Hiramatsu
@ 2020-08-27 16:39 ` Masami Hiramatsu
  2020-08-28 12:34   ` Guo Ren
  2020-08-27 16:39 ` [PATCH v3 07/16] ia64: " Masami Hiramatsu
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:39 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/csky/kernel/probes/kprobes.c |   78 +------------------------------------
 1 file changed, 3 insertions(+), 75 deletions(-)

diff --git a/arch/csky/kernel/probes/kprobes.c b/arch/csky/kernel/probes/kprobes.c
index f0f733b7ac5a..a891fb422e76 100644
--- a/arch/csky/kernel/probes/kprobes.c
+++ b/arch/csky/kernel/probes/kprobes.c
@@ -404,87 +404,15 @@ int __init arch_populate_kprobe_blacklist(void)
 
 void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address =
-		(unsigned long)&kretprobe_trampoline;
-	kprobe_opcode_t *correct_ret_addr = NULL;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because multiple functions in the call path have
-	 * return probes installed on them, and/or more than one
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always pushed into the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *	 function, the (chronologically) first instance's ret_addr
-	 *	 will be the real return address, and all the rest will
-	 *	 point to kretprobe_trampoline.
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-	correct_ret_addr = ri->ret_addr;
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		if (ri->rp && ri->rp->handler) {
-			__this_cpu_write(current_kprobe, &ri->rp->kp);
-			get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
-			ri->ret_addr = correct_ret_addr;
-			ri->rp->handler(ri, regs);
-			__this_cpu_write(current_kprobe, NULL);
-		}
-
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
-	return (void *)orig_ret_address;
+	return (void *)kretprobe_trampoline_handler(regs,
+			(unsigned long)&kretprobe_trampoline, NULL);
 }
 
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *)regs->lr;
+	ri->fp = NULL;
 	regs->lr = (unsigned long) &kretprobe_trampoline;
 }
 


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

* [PATCH v3 07/16] ia64: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (5 preceding siblings ...)
  2020-08-27 16:39 ` [PATCH v3 06/16] csky: " Masami Hiramatsu
@ 2020-08-27 16:39 ` Masami Hiramatsu
  2020-08-27 16:39 ` [PATCH v3 08/16] mips: " Masami Hiramatsu
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:39 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/ia64/kernel/kprobes.c |   79 ++------------------------------------------
 1 file changed, 4 insertions(+), 75 deletions(-)

diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 7a7df944d798..0e725ca9c60d 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -396,83 +396,11 @@ static void kretprobe_trampoline(void)
 {
 }
 
-/*
- * At this point the target function has been tricked into
- * returning into our trampoline.  Lookup the associated instance
- * and then:
- *    - call the handler function
- *    - cleanup by marking the instance as unused
- *    - long jump back to the original return address
- */
 int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address =
-		((struct fnptr *)kretprobe_trampoline)->ip;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because an multiple functions in the call path
-	 * have a return probe installed on them, and/or more than one return
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *       function, the first instance's ret_addr will point to the
-	 *       real return address, and all the rest will point to
-	 *       kretprobe_trampoline
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	regs->cr_iip = orig_ret_address;
-
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		if (ri->rp && ri->rp->handler)
-			ri->rp->handler(ri, regs);
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
+	regs->cr_iip = __kretprobe_trampoline_handler(regs,
+				(unsigned long)kretprobe_trampoline,
+				NULL);
 	/*
 	 * By returning a non-zero value, we are telling
 	 * kprobe_handler() that we don't want the post_handler
@@ -485,6 +413,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *)regs->b0;
+	ri->fp = NULL;
 
 	/* Replace the return addr with trampoline addr */
 	regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;


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

* [PATCH v3 08/16] mips: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (6 preceding siblings ...)
  2020-08-27 16:39 ` [PATCH v3 07/16] ia64: " Masami Hiramatsu
@ 2020-08-27 16:39 ` Masami Hiramatsu
  2020-08-27 16:39 ` [PATCH v3 09/16] parisc: " Masami Hiramatsu
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:39 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/mips/kernel/kprobes.c |   55 +++-----------------------------------------
 1 file changed, 4 insertions(+), 51 deletions(-)

diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c
index d043c2f897fc..b58f49b7555e 100644
--- a/arch/mips/kernel/kprobes.c
+++ b/arch/mips/kernel/kprobes.c
@@ -477,6 +477,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *) regs->regs[31];
+	ri->fp = NULL;
 
 	/* Replace the return addr with trampoline addr */
 	regs->regs[31] = (unsigned long)kretprobe_trampoline;
@@ -488,57 +489,9 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 static int __kprobes trampoline_probe_handler(struct kprobe *p,
 						struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address = (unsigned long)kretprobe_trampoline;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because an multiple functions in the call path
-	 * have a return probe installed on them, and/or more than one return
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *	 function, the first instance's ret_addr will point to the
-	 *	 real return address, and all the rest will point to
-	 *	 kretprobe_trampoline
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		if (ri->rp && ri->rp->handler)
-			ri->rp->handler(ri, regs);
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-	instruction_pointer(regs) = orig_ret_address;
-
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
+	instruction_pointer(regs) = __kretprobe_trampoline_handler(regs,
+				(unsigned long)kretprobe_trampoline,
+				NULL);
 	/*
 	 * By returning a non-zero value, we are telling
 	 * kprobe_handler() that we don't want the post_handler


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

* [PATCH v3 09/16] parisc: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (7 preceding siblings ...)
  2020-08-27 16:39 ` [PATCH v3 08/16] mips: " Masami Hiramatsu
@ 2020-08-27 16:39 ` Masami Hiramatsu
  2020-08-27 16:40 ` [PATCH v3 10/16] powerpc: " Masami Hiramatsu
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:39 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/parisc/kernel/kprobes.c |   78 +++---------------------------------------
 1 file changed, 6 insertions(+), 72 deletions(-)

diff --git a/arch/parisc/kernel/kprobes.c b/arch/parisc/kernel/kprobes.c
index 77ec51818916..2f9389ae91a3 100644
--- a/arch/parisc/kernel/kprobes.c
+++ b/arch/parisc/kernel/kprobes.c
@@ -191,80 +191,13 @@ static struct kprobe trampoline_p = {
 static int __kprobes trampoline_probe_handler(struct kprobe *p,
 					      struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address = (unsigned long)trampoline_p.addr;
-	kprobe_opcode_t *correct_ret_addr = NULL;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because multiple functions in the call path have
-	 * a return probe installed on them, and/or more than one return
-	 * probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *       function, the first instance's ret_addr will point to the
-	 *       real return address, and all the rest will point to
-	 *       kretprobe_trampoline
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-	correct_ret_addr = ri->ret_addr;
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		if (ri->rp && ri->rp->handler) {
-			__this_cpu_write(current_kprobe, &ri->rp->kp);
-			get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
-			ri->ret_addr = correct_ret_addr;
-			ri->rp->handler(ri, regs);
-			__this_cpu_write(current_kprobe, NULL);
-		}
-
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
+	unsigned long orig_ret_address;
 
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
+	orig_ret_address = __kretprobe_trampoline_handler(regs,
+			(unsigned long)trampoline_p.addr,
+			NULL);
 	instruction_pointer_set(regs, orig_ret_address);
+
 	return 1;
 }
 
@@ -272,6 +205,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *)regs->gr[2];
+	ri->fp = NULL;
 
 	/* Replace the return addr with trampoline addr. */
 	regs->gr[2] = (unsigned long)trampoline_p.addr;


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

* [PATCH v3 10/16] powerpc: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (8 preceding siblings ...)
  2020-08-27 16:39 ` [PATCH v3 09/16] parisc: " Masami Hiramatsu
@ 2020-08-27 16:40 ` Masami Hiramatsu
  2020-08-27 16:40 ` [PATCH v3 11/16] s390: " Masami Hiramatsu
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:40 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v2:
   Fix to use correct trampoline_address.
---
 arch/powerpc/kernel/kprobes.c |   55 ++++-------------------------------------
 1 file changed, 5 insertions(+), 50 deletions(-)

diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 6ab9b4d037c3..f136037750be 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -218,6 +218,7 @@ bool arch_kprobe_on_func_entry(unsigned long offset)
 void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *)regs->link;
+	ri->fp = NULL;
 
 	/* Replace the return addr with trampoline addr */
 	regs->link = (unsigned long)kretprobe_trampoline;
@@ -396,50 +397,11 @@ asm(".global kretprobe_trampoline\n"
  */
 static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because an multiple functions in the call path
-	 * have a return probe installed on them, and/or more than one return
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *       function, the first instance's ret_addr will point to the
-	 *       real return address, and all the rest will point to
-	 *       kretprobe_trampoline
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		if (ri->rp && ri->rp->handler)
-			ri->rp->handler(ri, regs);
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
+	unsigned long orig_ret_address;
 
+	orig_ret_address = __kretprobe_trampoline_handler(regs,
+			(unsigned long)&kretprobe_trampoline,
+			NULL);
 	/*
 	 * We get here through one of two paths:
 	 * 1. by taking a trap -> kprobe_handler() -> here
@@ -458,13 +420,6 @@ static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	regs->nip = orig_ret_address - 4;
 	regs->link = orig_ret_address;
 
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
-
 	return 0;
 }
 NOKPROBE_SYMBOL(trampoline_probe_handler);


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

* [PATCH v3 11/16] s390: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (9 preceding siblings ...)
  2020-08-27 16:40 ` [PATCH v3 10/16] powerpc: " Masami Hiramatsu
@ 2020-08-27 16:40 ` Masami Hiramatsu
  2020-08-27 16:40 ` [PATCH v3 12/16] sh: " Masami Hiramatsu
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:40 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/s390/kernel/kprobes.c |   81 ++------------------------------------------
 1 file changed, 4 insertions(+), 77 deletions(-)

diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index d2a71d872638..6009f08836f4 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -228,6 +228,7 @@ NOKPROBE_SYMBOL(pop_kprobe);
 void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14];
+	ri->fp = NULL;
 
 	/* Replace the return addr with trampoline addr */
 	regs->gprs[14] = (unsigned long) &kretprobe_trampoline;
@@ -331,83 +332,9 @@ static void __used kretprobe_trampoline_holder(void)
  */
 static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address;
-	unsigned long trampoline_address;
-	kprobe_opcode_t *correct_ret_addr;
-
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because an multiple functions in the call path
-	 * have a return probe installed on them, and/or more than one return
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *	 function, the first instance's ret_addr will point to the
-	 *	 real return address, and all the rest will point to
-	 *	 kretprobe_trampoline
-	 */
-	ri = NULL;
-	orig_ret_address = 0;
-	correct_ret_addr = NULL;
-	trampoline_address = (unsigned long) &kretprobe_trampoline;
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long) ri->ret_addr;
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-	correct_ret_addr = ri->ret_addr;
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		orig_ret_address = (unsigned long) ri->ret_addr;
-
-		if (ri->rp && ri->rp->handler) {
-			ri->ret_addr = correct_ret_addr;
-			ri->rp->handler(ri, regs);
-		}
-
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	regs->psw.addr = orig_ret_address;
-
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
+	regs->psw.addr = __kretprobe_trampoline_handler(regs,
+			(unsigned long) &kretprobe_trampoline,
+			NULL);
 	/*
 	 * By returning a non-zero value, we are telling
 	 * kprobe_handler() that we don't want the post_handler


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

* [PATCH v3 12/16] sh: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (10 preceding siblings ...)
  2020-08-27 16:40 ` [PATCH v3 11/16] s390: " Masami Hiramatsu
@ 2020-08-27 16:40 ` Masami Hiramatsu
  2020-08-27 16:40 ` [PATCH v3 13/16] sparc: " Masami Hiramatsu
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:40 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/sh/kernel/kprobes.c |   59 +++-------------------------------------------
 1 file changed, 4 insertions(+), 55 deletions(-)

diff --git a/arch/sh/kernel/kprobes.c b/arch/sh/kernel/kprobes.c
index 318296f48f1a..118927ab63af 100644
--- a/arch/sh/kernel/kprobes.c
+++ b/arch/sh/kernel/kprobes.c
@@ -204,6 +204,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *) regs->pr;
+	ri->fp = NULL;
 
 	/* Replace the return addr with trampoline addr */
 	regs->pr = (unsigned long)kretprobe_trampoline;
@@ -302,62 +303,10 @@ static void __used kretprobe_trampoline_holder(void)
  */
 int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
+	regs->pc = __kretprobe_trampoline_handler(regs,
+			(unsigned long)&kretprobe_trampoline, NULL);
 
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because an multiple functions in the call path
-	 * have a return probe installed on them, and/or more then one return
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *       function, the first instance's ret_addr will point to the
-	 *       real return address, and all the rest will point to
-	 *       kretprobe_trampoline
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		if (ri->rp && ri->rp->handler) {
-			__this_cpu_write(current_kprobe, &ri->rp->kp);
-			ri->rp->handler(ri, regs);
-			__this_cpu_write(current_kprobe, NULL);
-		}
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-	regs->pc = orig_ret_address;
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
-
-	return orig_ret_address;
+	return 1;
 }
 
 static int __kprobes post_kprobe_handler(struct pt_regs *regs)


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

* [PATCH v3 13/16] sparc: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (11 preceding siblings ...)
  2020-08-27 16:40 ` [PATCH v3 12/16] sh: " Masami Hiramatsu
@ 2020-08-27 16:40 ` Masami Hiramatsu
  2020-08-27 16:40 ` [PATCH v3 14/16] kprobes: Remove NMI context check Masami Hiramatsu
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:40 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 arch/sparc/kernel/kprobes.c |   52 +++----------------------------------------
 1 file changed, 4 insertions(+), 48 deletions(-)

diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c
index dfbca2470536..cd34aeaa3ebb 100644
--- a/arch/sparc/kernel/kprobes.c
+++ b/arch/sparc/kernel/kprobes.c
@@ -453,6 +453,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
 	ri->ret_addr = (kprobe_opcode_t *)(regs->u_regs[UREG_RETPC] + 8);
+	ri->fp = NULL;
 
 	/* Replace the return addr with trampoline addr */
 	regs->u_regs[UREG_RETPC] =
@@ -465,58 +466,13 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 static int __kprobes trampoline_probe_handler(struct kprobe *p,
 					      struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
-	struct hlist_node *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+	unsigned long orig_ret_address = 0;
 
-	INIT_HLIST_HEAD(&empty_rp);
-	kretprobe_hash_lock(current, &head, &flags);
-
-	/*
-	 * It is possible to have multiple instances associated with a given
-	 * task either because an multiple functions in the call path
-	 * have a return probe installed on them, and/or more than one return
-	 * return probe was registered for a target function.
-	 *
-	 * We can handle this because:
-	 *     - instances are always inserted at the head of the list
-	 *     - when multiple return probes are registered for the same
-	 *       function, the first instance's ret_addr will point to the
-	 *       real return address, and all the rest will point to
-	 *       kretprobe_trampoline
-	 */
-	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
-		if (ri->task != current)
-			/* another task is sharing our hash bucket */
-			continue;
-
-		if (ri->rp && ri->rp->handler)
-			ri->rp->handler(ri, regs);
-
-		orig_ret_address = (unsigned long)ri->ret_addr;
-		recycle_rp_inst(ri, &empty_rp);
-
-		if (orig_ret_address != trampoline_address)
-			/*
-			 * This is the real return address. Any other
-			 * instances associated with this task are for
-			 * other calls deeper on the call stack
-			 */
-			break;
-	}
-
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
+	orig_ret_address = __kretprobe_trampoline_handler(regs,
+			(unsigned long)&kretprobe_trampoline, NULL);
 	regs->tpc = orig_ret_address;
 	regs->tnpc = orig_ret_address + 4;
 
-	kretprobe_hash_unlock(current, &flags);
-
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
 	/*
 	 * By returning a non-zero value, we are telling
 	 * kprobe_handler() that we don't want the post_handler


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

* [PATCH v3 14/16] kprobes: Remove NMI context check
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (12 preceding siblings ...)
  2020-08-27 16:40 ` [PATCH v3 13/16] sparc: " Masami Hiramatsu
@ 2020-08-27 16:40 ` Masami Hiramatsu
  2020-08-27 16:40 ` [PATCH v3 15/16] kprobes: Free kretprobe_instance with rcu callback Masami Hiramatsu
  2020-08-27 16:40 ` [PATCH v3 16/16] kprobes: Make local used functions static Masami Hiramatsu
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:40 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Since the commit 9b38cc704e84 ("kretprobe: Prevent triggering
kretprobe from within kprobe_flush_task") sets a dummy current
kprobe in the trampoline handler by kprobe_busy_begin/end(),
it is not possible to run a kretprobe pre handler in kretprobe
trampoline handler context even with the NMI. If the NMI interrupts
a kretprobe_trampoline_handler() and it hits a kretprobe, the
2nd kretprobe will detect recursion correctly and it will be
skipped.
This means we have almost no double-lock issue on kretprobes by NMI.

The last one point is in cleanup_rp_inst() which also takes
kretprobe_table_lock without setting up current kprobes.
So adding kprobe_busy_begin/end() there allows us to remove
in_nmi() check.

The above commit applies kprobe_busy_begin/end() on x86, but
now all arch implementation are unified to generic one, we can
safely remove the in_nmi() check from arch independent code.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 kernel/kprobes.c |   16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index cbd2ad1af7b7..311033e4b8e4 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1359,7 +1359,8 @@ static void cleanup_rp_inst(struct kretprobe *rp)
 	struct hlist_node *next;
 	struct hlist_head *head;
 
-	/* No race here */
+	/* To avoid recursive kretprobe by NMI, set kprobe busy here */
+	kprobe_busy_begin();
 	for (hash = 0; hash < KPROBE_TABLE_SIZE; hash++) {
 		kretprobe_table_lock(hash, &flags);
 		head = &kretprobe_inst_table[hash];
@@ -1369,6 +1370,8 @@ static void cleanup_rp_inst(struct kretprobe *rp)
 		}
 		kretprobe_table_unlock(hash, &flags);
 	}
+	kprobe_busy_end();
+
 	free_rp_inst(rp);
 }
 NOKPROBE_SYMBOL(cleanup_rp_inst);
@@ -2038,17 +2041,6 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
 	unsigned long hash, flags = 0;
 	struct kretprobe_instance *ri;
 
-	/*
-	 * To avoid deadlocks, prohibit return probing in NMI contexts,
-	 * just skip the probe and increase the (inexact) 'nmissed'
-	 * statistical counter, so that the user is informed that
-	 * something happened:
-	 */
-	if (unlikely(in_nmi())) {
-		rp->nmissed++;
-		return 0;
-	}
-
 	/* TODO: consider to only swap the RA after the last pre_handler fired */
 	hash = hash_ptr(current, KPROBE_HASH_BITS);
 	raw_spin_lock_irqsave(&rp->lock, flags);


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

* [PATCH v3 15/16] kprobes: Free kretprobe_instance with rcu callback
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (13 preceding siblings ...)
  2020-08-27 16:40 ` [PATCH v3 14/16] kprobes: Remove NMI context check Masami Hiramatsu
@ 2020-08-27 16:40 ` Masami Hiramatsu
  2020-08-27 16:40 ` [PATCH v3 16/16] kprobes: Make local used functions static Masami Hiramatsu
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:40 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Free kretprobe_instance with rcu callback instead of directly
freeing the object in the kretprobe handler context.

This will make kretprobe run safer in NMI context.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v3:
   - Stick the rcu_head with hlist_node in kretprobe_instance
   - Make recycle_rp_inst() static
---
 include/linux/kprobes.h |    6 ++++--
 kernel/kprobes.c        |   25 ++++++-------------------
 2 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 46a7afcf5ec0..b4388abedecf 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -156,7 +156,10 @@ struct kretprobe {
 };
 
 struct kretprobe_instance {
-	struct hlist_node hlist;
+	union {
+		struct hlist_node hlist;
+		struct rcu_head rcu;
+	};
 	struct kretprobe *rp;
 	kprobe_opcode_t *ret_addr;
 	struct task_struct *task;
@@ -395,7 +398,6 @@ int register_kretprobes(struct kretprobe **rps, int num);
 void unregister_kretprobes(struct kretprobe **rps, int num);
 
 void kprobe_flush_task(struct task_struct *tk);
-void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
 
 int disable_kprobe(struct kprobe *kp);
 int enable_kprobe(struct kprobe *kp);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 311033e4b8e4..ce788574883b 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1223,8 +1223,7 @@ void kprobes_inc_nmissed_count(struct kprobe *p)
 }
 NOKPROBE_SYMBOL(kprobes_inc_nmissed_count);
 
-void recycle_rp_inst(struct kretprobe_instance *ri,
-		     struct hlist_head *head)
+static void recycle_rp_inst(struct kretprobe_instance *ri)
 {
 	struct kretprobe *rp = ri->rp;
 
@@ -1236,8 +1235,7 @@ void recycle_rp_inst(struct kretprobe_instance *ri,
 		hlist_add_head(&ri->hlist, &rp->free_instances);
 		raw_spin_unlock(&rp->lock);
 	} else
-		/* Unregistering */
-		hlist_add_head(&ri->hlist, head);
+		kfree_rcu(ri, rcu);
 }
 NOKPROBE_SYMBOL(recycle_rp_inst);
 
@@ -1313,7 +1311,7 @@ void kprobe_busy_end(void)
 void kprobe_flush_task(struct task_struct *tk)
 {
 	struct kretprobe_instance *ri;
-	struct hlist_head *head, empty_rp;
+	struct hlist_head *head;
 	struct hlist_node *tmp;
 	unsigned long hash, flags = 0;
 
@@ -1323,19 +1321,14 @@ void kprobe_flush_task(struct task_struct *tk)
 
 	kprobe_busy_begin();
 
-	INIT_HLIST_HEAD(&empty_rp);
 	hash = hash_ptr(tk, KPROBE_HASH_BITS);
 	head = &kretprobe_inst_table[hash];
 	kretprobe_table_lock(hash, &flags);
 	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
 		if (ri->task == tk)
-			recycle_rp_inst(ri, &empty_rp);
+			recycle_rp_inst(ri);
 	}
 	kretprobe_table_unlock(hash, &flags);
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
 
 	kprobe_busy_end();
 }
@@ -1936,13 +1929,12 @@ unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
 					void *frame_pointer)
 {
 	struct kretprobe_instance *ri = NULL;
-	struct hlist_head *head, empty_rp;
+	struct hlist_head *head;
 	struct hlist_node *tmp;
 	unsigned long flags, orig_ret_address = 0;
 	kprobe_opcode_t *correct_ret_addr = NULL;
 	bool skipped = false;
 
-	INIT_HLIST_HEAD(&empty_rp);
 	kretprobe_hash_lock(current, &head, &flags);
 
 	/*
@@ -2009,7 +2001,7 @@ unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
 			__this_cpu_write(current_kprobe, &kprobe_busy);
 		}
 
-		recycle_rp_inst(ri, &empty_rp);
+		recycle_rp_inst(ri);
 
 		if (orig_ret_address != trampoline_address)
 			/*
@@ -2022,11 +2014,6 @@ unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
 
 	kretprobe_hash_unlock(current, &flags);
 
-	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
-		hlist_del(&ri->hlist);
-		kfree(ri);
-	}
-
 	return orig_ret_address;
 }
 NOKPROBE_SYMBOL(__kretprobe_trampoline_handler)


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

* [PATCH v3 16/16] kprobes: Make local used functions static
  2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
                   ` (14 preceding siblings ...)
  2020-08-27 16:40 ` [PATCH v3 15/16] kprobes: Free kretprobe_instance with rcu callback Masami Hiramatsu
@ 2020-08-27 16:40 ` Masami Hiramatsu
  15 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-27 16:40 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra
  Cc: Eddy Wu, x86, David S . Miller, Steven Rostedt, Ingo Molnar,
	Naveen N . Rao, Anil S Keshavamurthy, linux-arch, guoren

Since we unified the kretprobe trampoline handler from arch/* code,
some functions and objects no need to be exported anymore.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 include/linux/kprobes.h |   15 ---------------
 kernel/kprobes.c        |   12 ++++++++----
 2 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index b4388abedecf..e2dbf5bb7560 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -190,7 +190,6 @@ static inline int kprobes_built_in(void)
 	return 1;
 }
 
-extern struct kprobe kprobe_busy;
 void kprobe_busy_begin(void);
 void kprobe_busy_end(void);
 
@@ -235,16 +234,6 @@ static inline int arch_trampoline_kprobe(struct kprobe *p)
 
 extern struct kretprobe_blackpoint kretprobe_blacklist[];
 
-static inline void kretprobe_assert(struct kretprobe_instance *ri,
-	unsigned long orig_ret_address, unsigned long trampoline_address)
-{
-	if (!orig_ret_address || (orig_ret_address == trampoline_address)) {
-		printk("kretprobe BUG!: Processing kretprobe %p @ %p\n",
-				ri->rp, ri->rp->kp.addr);
-		BUG();
-	}
-}
-
 #ifdef CONFIG_KPROBES_SANITY_TEST
 extern int init_test_probes(void);
 #else
@@ -364,10 +353,6 @@ int arch_check_ftrace_location(struct kprobe *p);
 
 /* Get the kprobe at this addr (if any) - called with preemption disabled */
 struct kprobe *get_kprobe(void *addr);
-void kretprobe_hash_lock(struct task_struct *tsk,
-			 struct hlist_head **head, unsigned long *flags);
-void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags);
-struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
 
 /* kprobe_running() will just return the current_kprobe on this CPU */
 static inline struct kprobe *kprobe_running(void)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index ce788574883b..55874dc1c182 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1239,7 +1239,7 @@ static void recycle_rp_inst(struct kretprobe_instance *ri)
 }
 NOKPROBE_SYMBOL(recycle_rp_inst);
 
-void kretprobe_hash_lock(struct task_struct *tsk,
+static void kretprobe_hash_lock(struct task_struct *tsk,
 			 struct hlist_head **head, unsigned long *flags)
 __acquires(hlist_lock)
 {
@@ -1261,7 +1261,7 @@ __acquires(hlist_lock)
 }
 NOKPROBE_SYMBOL(kretprobe_table_lock);
 
-void kretprobe_hash_unlock(struct task_struct *tsk,
+static void kretprobe_hash_unlock(struct task_struct *tsk,
 			   unsigned long *flags)
 __releases(hlist_lock)
 {
@@ -1282,7 +1282,7 @@ __releases(hlist_lock)
 }
 NOKPROBE_SYMBOL(kretprobe_table_unlock);
 
-struct kprobe kprobe_busy = {
+static struct kprobe kprobe_busy = {
 	.addr = (void *) get_kprobe,
 };
 
@@ -1983,7 +1983,11 @@ unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
 			break;
 	}
 
-	kretprobe_assert(ri, orig_ret_address, trampoline_address);
+	if (!orig_ret_address || (orig_ret_address == trampoline_address)) {
+		pr_err("kretprobe BUG!: Processing kretprobe %p @ %p\n",
+				ri->rp, ri->rp->kp.addr);
+		BUG();
+	}
 
 	correct_ret_addr = ri->ret_addr;
 	hlist_for_each_entry_safe(ri, tmp, head, hlist) {


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

* Re: [PATCH v3 01/16] kprobes: Add generic kretprobe trampoline handler
  2020-08-27 16:38 ` [PATCH v3 01/16] kprobes: Add generic kretprobe trampoline handler Masami Hiramatsu
@ 2020-08-28  1:57   ` Masami Hiramatsu
  0 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-28  1:57 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: linux-kernel, Peter Zijlstra, Eddy Wu, x86, David S . Miller,
	Steven Rostedt, Ingo Molnar, Naveen N . Rao,
	Anil S Keshavamurthy, linux-arch, guoren

On Fri, 28 Aug 2020 01:38:44 +0900
Masami Hiramatsu <mhiramat@kernel.org> wrote:

> +unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
> +					unsigned long trampoline_address,
> +					void *frame_pointer)
> +{
> +	struct kretprobe_instance *ri = NULL;
> +	struct hlist_head *head, empty_rp;
> +	struct hlist_node *tmp;
> +	unsigned long flags, orig_ret_address = 0;
> +	kprobe_opcode_t *correct_ret_addr = NULL;
> +	bool skipped = false;
> +
> +	INIT_HLIST_HEAD(&empty_rp);
> +	kretprobe_hash_lock(current, &head, &flags);
> +
> +	/*
> +	 * It is possible to have multiple instances associated with a given
> +	 * task either because multiple functions in the call path have
> +	 * return probes installed on them, and/or more than one
> +	 * return probe was registered for a target function.
> +	 *
> +	 * We can handle this because:
> +	 *     - instances are always pushed into the head of the list
> +	 *     - when multiple return probes are registered for the same
> +	 *	 function, the (chronologically) first instance's ret_addr
> +	 *	 will be the real return address, and all the rest will
> +	 *	 point to kretprobe_trampoline.
> +	 */
> +	hlist_for_each_entry(ri, head, hlist) {
> +		if (ri->task != current)
> +			/* another task is sharing our hash bucket */
> +			continue;
> +		/*
> +		 * Return probes must be pushed on this hash list correct
> +		 * order (same as return order) so that it can be popped
> +		 * correctly. However, if we find it is pushed it incorrect
> +		 * order, this means we find a function which should not be
> +		 * probed, because the wrong order entry is pushed on the
> +		 * path of processing other kretprobe itself.
> +		 */
> +		if (ri->fp != frame_pointer) {
> +			if (!skipped)
> +				pr_warn("kretprobe is stacked incorrectly. Trying to fixup.\n");
> +			skipped = true;
> +			continue;
> +		}
> +
> +		orig_ret_address = (unsigned long)ri->ret_addr;
> +		if (skipped)
> +			pr_warn("%ps must be blacklisted because of incorrect kretprobe order\n",
> +				ri->rp->kp.addr);
> +
> +		if (orig_ret_address != trampoline_address)
> +			/*
> +			 * This is the real return address. Any other
> +			 * instances associated with this task are for
> +			 * other calls deeper on the call stack
> +			 */
> +			break;
> +	}
> +
> +	kretprobe_assert(ri, orig_ret_address, trampoline_address);
> +
> +	correct_ret_addr = ri->ret_addr;

Oops, here is an insane code... why we have orig_ret_address *and* correct_ret_addr?
I'll clean this up.

Thanks,

-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v3 06/16] csky: kprobes: Use generic kretprobe trampoline handler
  2020-08-27 16:39 ` [PATCH v3 06/16] csky: " Masami Hiramatsu
@ 2020-08-28 12:34   ` Guo Ren
  2020-08-29  9:31     ` Masami Hiramatsu
  0 siblings, 1 reply; 20+ messages in thread
From: Guo Ren @ 2020-08-28 12:34 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Linux Kernel Mailing List, Peter Zijlstra, Eddy Wu, x86,
	David S . Miller, Steven Rostedt, Ingo Molnar, Naveen N . Rao,
	Anil S Keshavamurthy, linux-arch

Looks more clear.

Acked-by: Guo Ren <guoren@kernel.org>

On Fri, Aug 28, 2020 at 12:39 AM Masami Hiramatsu <mhiramat@kernel.org> wrote:
>
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  arch/csky/kernel/probes/kprobes.c |   78 +------------------------------------
>  1 file changed, 3 insertions(+), 75 deletions(-)
>
> diff --git a/arch/csky/kernel/probes/kprobes.c b/arch/csky/kernel/probes/kprobes.c
> index f0f733b7ac5a..a891fb422e76 100644
> --- a/arch/csky/kernel/probes/kprobes.c
> +++ b/arch/csky/kernel/probes/kprobes.c
> @@ -404,87 +404,15 @@ int __init arch_populate_kprobe_blacklist(void)
>
>  void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
>  {
> -       struct kretprobe_instance *ri = NULL;
> -       struct hlist_head *head, empty_rp;
> -       struct hlist_node *tmp;
> -       unsigned long flags, orig_ret_address = 0;
> -       unsigned long trampoline_address =
> -               (unsigned long)&kretprobe_trampoline;
> -       kprobe_opcode_t *correct_ret_addr = NULL;
> -
> -       INIT_HLIST_HEAD(&empty_rp);
> -       kretprobe_hash_lock(current, &head, &flags);
> -
> -       /*
> -        * It is possible to have multiple instances associated with a given
> -        * task either because multiple functions in the call path have
> -        * return probes installed on them, and/or more than one
> -        * return probe was registered for a target function.
> -        *
> -        * We can handle this because:
> -        *     - instances are always pushed into the head of the list
> -        *     - when multiple return probes are registered for the same
> -        *       function, the (chronologically) first instance's ret_addr
> -        *       will be the real return address, and all the rest will
> -        *       point to kretprobe_trampoline.
> -        */
> -       hlist_for_each_entry_safe(ri, tmp, head, hlist) {
> -               if (ri->task != current)
> -                       /* another task is sharing our hash bucket */
> -                       continue;
> -
> -               orig_ret_address = (unsigned long)ri->ret_addr;
> -
> -               if (orig_ret_address != trampoline_address)
> -                       /*
> -                        * This is the real return address. Any other
> -                        * instances associated with this task are for
> -                        * other calls deeper on the call stack
> -                        */
> -                       break;
> -       }
> -
> -       kretprobe_assert(ri, orig_ret_address, trampoline_address);
> -
> -       correct_ret_addr = ri->ret_addr;
> -       hlist_for_each_entry_safe(ri, tmp, head, hlist) {
> -               if (ri->task != current)
> -                       /* another task is sharing our hash bucket */
> -                       continue;
> -
> -               orig_ret_address = (unsigned long)ri->ret_addr;
> -               if (ri->rp && ri->rp->handler) {
> -                       __this_cpu_write(current_kprobe, &ri->rp->kp);
> -                       get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
> -                       ri->ret_addr = correct_ret_addr;
> -                       ri->rp->handler(ri, regs);
> -                       __this_cpu_write(current_kprobe, NULL);
> -               }
> -
> -               recycle_rp_inst(ri, &empty_rp);
> -
> -               if (orig_ret_address != trampoline_address)
> -                       /*
> -                        * This is the real return address. Any other
> -                        * instances associated with this task are for
> -                        * other calls deeper on the call stack
> -                        */
> -                       break;
> -       }
> -
> -       kretprobe_hash_unlock(current, &flags);
> -
> -       hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
> -               hlist_del(&ri->hlist);
> -               kfree(ri);
> -       }
> -       return (void *)orig_ret_address;
> +       return (void *)kretprobe_trampoline_handler(regs,
> +                       (unsigned long)&kretprobe_trampoline, NULL);
>  }
>
>  void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
>                                       struct pt_regs *regs)
>  {
>         ri->ret_addr = (kprobe_opcode_t *)regs->lr;
> +       ri->fp = NULL;
>         regs->lr = (unsigned long) &kretprobe_trampoline;
>  }
>
>


-- 
Best Regards
 Guo Ren

ML: https://lore.kernel.org/linux-csky/

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

* Re: [PATCH v3 06/16] csky: kprobes: Use generic kretprobe trampoline handler
  2020-08-28 12:34   ` Guo Ren
@ 2020-08-29  9:31     ` Masami Hiramatsu
  0 siblings, 0 replies; 20+ messages in thread
From: Masami Hiramatsu @ 2020-08-29  9:31 UTC (permalink / raw)
  To: Guo Ren
  Cc: Linux Kernel Mailing List, Peter Zijlstra, Eddy Wu, x86,
	David S . Miller, Steven Rostedt, Ingo Molnar, Naveen N . Rao,
	Anil S Keshavamurthy, linux-arch

On Fri, 28 Aug 2020 20:34:22 +0800
Guo Ren <guoren@kernel.org> wrote:

> Looks more clear.
> 
> Acked-by: Guo Ren <guoren@kernel.org>

Thanks Guo! I'll add it to the next version.

> 
> On Fri, Aug 28, 2020 at 12:39 AM Masami Hiramatsu <mhiramat@kernel.org> wrote:
> >
> > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> > ---
> >  arch/csky/kernel/probes/kprobes.c |   78 +------------------------------------
> >  1 file changed, 3 insertions(+), 75 deletions(-)
> >
> > diff --git a/arch/csky/kernel/probes/kprobes.c b/arch/csky/kernel/probes/kprobes.c
> > index f0f733b7ac5a..a891fb422e76 100644
> > --- a/arch/csky/kernel/probes/kprobes.c
> > +++ b/arch/csky/kernel/probes/kprobes.c
> > @@ -404,87 +404,15 @@ int __init arch_populate_kprobe_blacklist(void)
> >
> >  void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
> >  {
> > -       struct kretprobe_instance *ri = NULL;
> > -       struct hlist_head *head, empty_rp;
> > -       struct hlist_node *tmp;
> > -       unsigned long flags, orig_ret_address = 0;
> > -       unsigned long trampoline_address =
> > -               (unsigned long)&kretprobe_trampoline;
> > -       kprobe_opcode_t *correct_ret_addr = NULL;
> > -
> > -       INIT_HLIST_HEAD(&empty_rp);
> > -       kretprobe_hash_lock(current, &head, &flags);
> > -
> > -       /*
> > -        * It is possible to have multiple instances associated with a given
> > -        * task either because multiple functions in the call path have
> > -        * return probes installed on them, and/or more than one
> > -        * return probe was registered for a target function.
> > -        *
> > -        * We can handle this because:
> > -        *     - instances are always pushed into the head of the list
> > -        *     - when multiple return probes are registered for the same
> > -        *       function, the (chronologically) first instance's ret_addr
> > -        *       will be the real return address, and all the rest will
> > -        *       point to kretprobe_trampoline.
> > -        */
> > -       hlist_for_each_entry_safe(ri, tmp, head, hlist) {
> > -               if (ri->task != current)
> > -                       /* another task is sharing our hash bucket */
> > -                       continue;
> > -
> > -               orig_ret_address = (unsigned long)ri->ret_addr;
> > -
> > -               if (orig_ret_address != trampoline_address)
> > -                       /*
> > -                        * This is the real return address. Any other
> > -                        * instances associated with this task are for
> > -                        * other calls deeper on the call stack
> > -                        */
> > -                       break;
> > -       }
> > -
> > -       kretprobe_assert(ri, orig_ret_address, trampoline_address);
> > -
> > -       correct_ret_addr = ri->ret_addr;
> > -       hlist_for_each_entry_safe(ri, tmp, head, hlist) {
> > -               if (ri->task != current)
> > -                       /* another task is sharing our hash bucket */
> > -                       continue;
> > -
> > -               orig_ret_address = (unsigned long)ri->ret_addr;
> > -               if (ri->rp && ri->rp->handler) {
> > -                       __this_cpu_write(current_kprobe, &ri->rp->kp);
> > -                       get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
> > -                       ri->ret_addr = correct_ret_addr;
> > -                       ri->rp->handler(ri, regs);
> > -                       __this_cpu_write(current_kprobe, NULL);
> > -               }
> > -
> > -               recycle_rp_inst(ri, &empty_rp);
> > -
> > -               if (orig_ret_address != trampoline_address)
> > -                       /*
> > -                        * This is the real return address. Any other
> > -                        * instances associated with this task are for
> > -                        * other calls deeper on the call stack
> > -                        */
> > -                       break;
> > -       }
> > -
> > -       kretprobe_hash_unlock(current, &flags);
> > -
> > -       hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
> > -               hlist_del(&ri->hlist);
> > -               kfree(ri);
> > -       }
> > -       return (void *)orig_ret_address;
> > +       return (void *)kretprobe_trampoline_handler(regs,
> > +                       (unsigned long)&kretprobe_trampoline, NULL);
> >  }
> >
> >  void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
> >                                       struct pt_regs *regs)
> >  {
> >         ri->ret_addr = (kprobe_opcode_t *)regs->lr;
> > +       ri->fp = NULL;
> >         regs->lr = (unsigned long) &kretprobe_trampoline;
> >  }
> >
> >
> 
> 
> -- 
> Best Regards
>  Guo Ren
> 
> ML: https://lore.kernel.org/linux-csky/


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

end of thread, other threads:[~2020-08-29  9:31 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-27 16:38 [PATCH v3 00/16] kprobes: Unify kretprobe trampoline handlers Masami Hiramatsu
2020-08-27 16:38 ` [PATCH v3 01/16] kprobes: Add generic kretprobe trampoline handler Masami Hiramatsu
2020-08-28  1:57   ` Masami Hiramatsu
2020-08-27 16:38 ` [PATCH v3 02/16] x86/kprobes: Use " Masami Hiramatsu
2020-08-27 16:39 ` [PATCH v3 03/16] arm: kprobes: " Masami Hiramatsu
2020-08-27 16:39 ` [PATCH v3 04/16] arm64: " Masami Hiramatsu
2020-08-27 16:39 ` [PATCH v3 05/16] arc: " Masami Hiramatsu
2020-08-27 16:39 ` [PATCH v3 06/16] csky: " Masami Hiramatsu
2020-08-28 12:34   ` Guo Ren
2020-08-29  9:31     ` Masami Hiramatsu
2020-08-27 16:39 ` [PATCH v3 07/16] ia64: " Masami Hiramatsu
2020-08-27 16:39 ` [PATCH v3 08/16] mips: " Masami Hiramatsu
2020-08-27 16:39 ` [PATCH v3 09/16] parisc: " Masami Hiramatsu
2020-08-27 16:40 ` [PATCH v3 10/16] powerpc: " Masami Hiramatsu
2020-08-27 16:40 ` [PATCH v3 11/16] s390: " Masami Hiramatsu
2020-08-27 16:40 ` [PATCH v3 12/16] sh: " Masami Hiramatsu
2020-08-27 16:40 ` [PATCH v3 13/16] sparc: " Masami Hiramatsu
2020-08-27 16:40 ` [PATCH v3 14/16] kprobes: Remove NMI context check Masami Hiramatsu
2020-08-27 16:40 ` [PATCH v3 15/16] kprobes: Free kretprobe_instance with rcu callback Masami Hiramatsu
2020-08-27 16:40 ` [PATCH v3 16/16] kprobes: Make local used functions static Masami Hiramatsu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.