All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] kprobes: Remove NMI context check
@ 2020-12-10 15:30 Masami Hiramatsu
  2020-12-10 15:31 ` [PATCH 2/2] kprobes: Tell lockdep about kprobe nesting Masami Hiramatsu
  2020-12-11 14:47 ` [PATCH 1/2] kprobes: Remove NMI context check Greg KH
  0 siblings, 2 replies; 3+ messages in thread
From: Masami Hiramatsu @ 2020-12-10 15:30 UTC (permalink / raw)
  To: stable
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
	H . Peter Anvin, linux-kernel, Naveen N . Rao,
	Anil S Keshavamurthy, David S . Miller, Masami Hiramatsu,
	Solar Designer, Eddy_Wu, Peter Zijlstra

commit e03b4a084ea6b0a18b0e874baec439e69090c168 upstream.

The in_nmi() check in pre_handler_kretprobe() is meant to avoid
recursion, and blindly assumes that anything NMI is recursive.

However, since commit:

  9b38cc704e84 ("kretprobe: Prevent triggering kretprobe from within kprobe_flush_task")

there is a better way to detect and avoid actual recursion.

By setting a dummy kprobe, any actual exceptions will terminate early
(by trying to handle the dummy kprobe), and recursion will not happen.

Employ this to avoid the kretprobe_table_lock() recursion, replacing
the over-eager in_nmi() check.

Cc: stable@vger.kernel.org # 5.9.x
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://lkml.kernel.org/r/159870615628.1229682.6087311596892125907.stgit@devnote2
---
 kernel/kprobes.c |   16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index e995541d277d..b885d884603d 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);
@@ -1937,17 +1940,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] 3+ messages in thread

* [PATCH 2/2] kprobes: Tell lockdep about kprobe nesting
  2020-12-10 15:30 [PATCH 1/2] kprobes: Remove NMI context check Masami Hiramatsu
@ 2020-12-10 15:31 ` Masami Hiramatsu
  2020-12-11 14:47 ` [PATCH 1/2] kprobes: Remove NMI context check Greg KH
  1 sibling, 0 replies; 3+ messages in thread
From: Masami Hiramatsu @ 2020-12-10 15:31 UTC (permalink / raw)
  To: stable
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
	H . Peter Anvin, linux-kernel, Naveen N . Rao,
	Anil S Keshavamurthy, David S . Miller, Masami Hiramatsu,
	Solar Designer, Eddy_Wu, Peter Zijlstra

From: Steven Rostedt (VMware) <rostedt@goodmis.org>

commit 645f224e7ba2f4200bf163153d384ceb0de5462e upstream.

Since the kprobe handlers have protection that prohibits other handlers from
executing in other contexts (like if an NMI comes in while processing a
kprobe, and executes the same kprobe, it will get fail with a "busy"
return). Lockdep is unaware of this protection. Use lockdep's nesting api to
differentiate between locks taken in INT3 context and other context to
suppress the false warnings.

Link: https://lore.kernel.org/r/20201102160234.fa0ae70915ad9e2b21c08b85@kernel.org

Cc: stable@vger.kernel.org # 5.9.x
Cc: Peter Zijlstra <peterz@infradead.org>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 kernel/kprobes.c |   25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index b885d884603d..1b7fd1ab8ddc 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1250,7 +1250,13 @@ __acquires(hlist_lock)
 
 	*head = &kretprobe_inst_table[hash];
 	hlist_lock = kretprobe_table_lock_ptr(hash);
-	raw_spin_lock_irqsave(hlist_lock, *flags);
+	/*
+	 * Nested is a workaround that will soon not be needed.
+	 * There's other protections that make sure the same lock
+	 * is not taken on the same CPU that lockdep is unaware of.
+	 * Differentiate when it is taken in NMI context.
+	 */
+	raw_spin_lock_irqsave_nested(hlist_lock, *flags, !!in_nmi());
 }
 NOKPROBE_SYMBOL(kretprobe_hash_lock);
 
@@ -1259,7 +1265,13 @@ static void kretprobe_table_lock(unsigned long hash,
 __acquires(hlist_lock)
 {
 	raw_spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
-	raw_spin_lock_irqsave(hlist_lock, *flags);
+	/*
+	 * Nested is a workaround that will soon not be needed.
+	 * There's other protections that make sure the same lock
+	 * is not taken on the same CPU that lockdep is unaware of.
+	 * Differentiate when it is taken in NMI context.
+	 */
+	raw_spin_lock_irqsave_nested(hlist_lock, *flags, !!in_nmi());
 }
 NOKPROBE_SYMBOL(kretprobe_table_lock);
 
@@ -1942,7 +1954,12 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
 
 	/* 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);
+	/*
+	 * Nested is a workaround that will soon not be needed.
+	 * There's other protections that make sure the same lock
+	 * is not taken on the same CPU that lockdep is unaware of.
+	 */
+	raw_spin_lock_irqsave_nested(&rp->lock, flags, 1);
 	if (!hlist_empty(&rp->free_instances)) {
 		ri = hlist_entry(rp->free_instances.first,
 				struct kretprobe_instance, hlist);
@@ -1953,7 +1970,7 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
 		ri->task = current;
 
 		if (rp->entry_handler && rp->entry_handler(ri, regs)) {
-			raw_spin_lock_irqsave(&rp->lock, flags);
+			raw_spin_lock_irqsave_nested(&rp->lock, flags, 1);
 			hlist_add_head(&ri->hlist, &rp->free_instances);
 			raw_spin_unlock_irqrestore(&rp->lock, flags);
 			return 0;


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

* Re: [PATCH 1/2] kprobes: Remove NMI context check
  2020-12-10 15:30 [PATCH 1/2] kprobes: Remove NMI context check Masami Hiramatsu
  2020-12-10 15:31 ` [PATCH 2/2] kprobes: Tell lockdep about kprobe nesting Masami Hiramatsu
@ 2020-12-11 14:47 ` Greg KH
  1 sibling, 0 replies; 3+ messages in thread
From: Greg KH @ 2020-12-11 14:47 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: stable, Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
	H . Peter Anvin, linux-kernel, Naveen N . Rao,
	Anil S Keshavamurthy, David S . Miller, Solar Designer, Eddy_Wu,
	Peter Zijlstra

On Fri, Dec 11, 2020 at 12:30:58AM +0900, Masami Hiramatsu wrote:
> commit e03b4a084ea6b0a18b0e874baec439e69090c168 upstream.

Both patches now queued up, thanks.

greg k-h

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

end of thread, other threads:[~2020-12-11 15:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-10 15:30 [PATCH 1/2] kprobes: Remove NMI context check Masami Hiramatsu
2020-12-10 15:31 ` [PATCH 2/2] kprobes: Tell lockdep about kprobe nesting Masami Hiramatsu
2020-12-11 14:47 ` [PATCH 1/2] kprobes: Remove NMI context check Greg KH

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.