linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [for-linus][PATCH 0/3] tracing/ftrace: trace_printk buffer fix and ftrace recursion fixes
@ 2020-10-31 13:06 Steven Rostedt
  2020-10-31 13:06 ` [for-linus][PATCH 1/3] tracing: Fix out of bounds write in get_trace_buf Steven Rostedt
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Steven Rostedt @ 2020-10-31 13:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Ingo Molnar, Andrew Morton, Miroslav Benes, Josh Poimboeuf,
	Jiri Kosina, Petr Mladek

The indexing of the different context buffers had an off by one error.

The recursion protection for ftrace callbacks had two bugs.
 One that would make NMIs always appear to be recursing
 The other is trasitions between interrupt context could also cause
 false positives and miss tracing those functions.

Qiujun Huang (1):
      tracing: Fix out of bounds write in get_trace_buf

Steven Rostedt (VMware) (2):
      ftrace: Fix recursion check for NMI test
      ftrace: Handle tracing when switching between context

----
 kernel/trace/trace.c          |  2 +-
 kernel/trace/trace.h          | 26 +++++++++++++++++++++++---
 kernel/trace/trace_selftest.c |  9 +++++++--
 3 files changed, 31 insertions(+), 6 deletions(-)

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

* [for-linus][PATCH 1/3] tracing: Fix out of bounds write in get_trace_buf
  2020-10-31 13:06 [for-linus][PATCH 0/3] tracing/ftrace: trace_printk buffer fix and ftrace recursion fixes Steven Rostedt
@ 2020-10-31 13:06 ` Steven Rostedt
  2020-10-31 13:06 ` [for-linus][PATCH 2/3] ftrace: Fix recursion check for NMI test Steven Rostedt
  2020-10-31 13:06 ` [for-linus][PATCH 3/3] ftrace: Handle tracing when switching between context Steven Rostedt
  2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2020-10-31 13:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Ingo Molnar, Andrew Morton, Miroslav Benes, Josh Poimboeuf,
	Jiri Kosina, Petr Mladek, stable, Qiujun Huang

From: Qiujun Huang <hqjagain@gmail.com>

The nesting count of trace_printk allows for 4 levels of nesting. The
nesting counter starts at zero and is incremented before being used to
retrieve the current context's buffer. But the index to the buffer uses the
nesting counter after it was incremented, and not its original number,
which in needs to do.

Link: https://lkml.kernel.org/r/20201029161905.4269-1-hqjagain@gmail.com

Cc: stable@vger.kernel.org
Fixes: 3d9622c12c887 ("tracing: Add barrier to trace_printk() buffer nesting modification")
Signed-off-by: Qiujun Huang <hqjagain@gmail.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 kernel/trace/trace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 528971714fc6..daa96215e294 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3132,7 +3132,7 @@ static char *get_trace_buf(void)
 
 	/* Interrupts must see nesting incremented before we use the buffer */
 	barrier();
-	return &buffer->buffer[buffer->nesting][0];
+	return &buffer->buffer[buffer->nesting - 1][0];
 }
 
 static void put_trace_buf(void)
-- 
2.28.0



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

* [for-linus][PATCH 2/3] ftrace: Fix recursion check for NMI test
  2020-10-31 13:06 [for-linus][PATCH 0/3] tracing/ftrace: trace_printk buffer fix and ftrace recursion fixes Steven Rostedt
  2020-10-31 13:06 ` [for-linus][PATCH 1/3] tracing: Fix out of bounds write in get_trace_buf Steven Rostedt
@ 2020-10-31 13:06 ` Steven Rostedt
  2020-10-31 13:06 ` [for-linus][PATCH 3/3] ftrace: Handle tracing when switching between context Steven Rostedt
  2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2020-10-31 13:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Ingo Molnar, Andrew Morton, Miroslav Benes, Josh Poimboeuf,
	Jiri Kosina, Petr Mladek, stable

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

The code that checks recursion will work to only do the recursion check once
if there's nested checks. The top one will do the check, the other nested
checks will see recursion was already checked and return zero for its "bit".
On the return side, nothing will be done if the "bit" is zero.

The problem is that zero is returned for the "good" bit when in NMI context.
This will set the bit for NMIs making it look like *all* NMI tracing is
recursing, and prevent tracing of anything in NMI context!

The simple fix is to return "bit + 1" and subtract that bit on the end to
get the real bit.

Cc: stable@vger.kernel.org
Fixes: edc15cafcbfa3 ("tracing: Avoid unnecessary multiple recursion checks")
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 kernel/trace/trace.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index f3f5e77123ad..fee535a89560 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -698,7 +698,7 @@ static __always_inline int trace_test_and_set_recursion(int start, int max)
 	current->trace_recursion = val;
 	barrier();
 
-	return bit;
+	return bit + 1;
 }
 
 static __always_inline void trace_clear_recursion(int bit)
@@ -708,6 +708,7 @@ static __always_inline void trace_clear_recursion(int bit)
 	if (!bit)
 		return;
 
+	bit--;
 	bit = 1 << bit;
 	val &= ~bit;
 
-- 
2.28.0



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

* [for-linus][PATCH 3/3] ftrace: Handle tracing when switching between context
  2020-10-31 13:06 [for-linus][PATCH 0/3] tracing/ftrace: trace_printk buffer fix and ftrace recursion fixes Steven Rostedt
  2020-10-31 13:06 ` [for-linus][PATCH 1/3] tracing: Fix out of bounds write in get_trace_buf Steven Rostedt
  2020-10-31 13:06 ` [for-linus][PATCH 2/3] ftrace: Fix recursion check for NMI test Steven Rostedt
@ 2020-10-31 13:06 ` Steven Rostedt
  2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2020-10-31 13:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Ingo Molnar, Andrew Morton, Miroslav Benes, Josh Poimboeuf,
	Jiri Kosina, Petr Mladek, stable

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

When an interrupt or NMI comes in and switches the context, there's a delay
from when the preempt_count() shows the update. As the preempt_count() is
used to detect recursion having each context have its own bit get set when
tracing starts, and if that bit is already set, it is considered a recursion
and the function exits. But if this happens in that section where context
has changed but preempt_count() has not been updated, this will be
incorrectly flagged as a recursion.

To handle this case, create another bit call TRANSITION and test it if the
current context bit is already set. Flag the call as a recursion if the
TRANSITION bit is already set, and if not, set it and continue. The
TRANSITION bit will be cleared normally on the return of the function that
set it, or if the current context bit is clear, set it and clear the
TRANSITION bit to allow for another transition between the current context
and an even higher one.

Cc: stable@vger.kernel.org
Fixes: edc15cafcbfa3 ("tracing: Avoid unnecessary multiple recursion checks")
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 kernel/trace/trace.h          | 23 +++++++++++++++++++++--
 kernel/trace/trace_selftest.c |  9 +++++++--
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index fee535a89560..1dadef445cd1 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -637,6 +637,12 @@ enum {
 	 * function is called to clear it.
 	 */
 	TRACE_GRAPH_NOTRACE_BIT,
+
+	/*
+	 * When transitioning between context, the preempt_count() may
+	 * not be correct. Allow for a single recursion to cover this case.
+	 */
+	TRACE_TRANSITION_BIT,
 };
 
 #define trace_recursion_set(bit)	do { (current)->trace_recursion |= (1<<(bit)); } while (0)
@@ -691,8 +697,21 @@ static __always_inline int trace_test_and_set_recursion(int start, int max)
 		return 0;
 
 	bit = trace_get_context_bit() + start;
-	if (unlikely(val & (1 << bit)))
-		return -1;
+	if (unlikely(val & (1 << bit))) {
+		/*
+		 * It could be that preempt_count has not been updated during
+		 * a switch between contexts. Allow for a single recursion.
+		 */
+		bit = TRACE_TRANSITION_BIT;
+		if (trace_recursion_test(bit))
+			return -1;
+		trace_recursion_set(bit);
+		barrier();
+		return bit + 1;
+	}
+
+	/* Normal check passed, clear the transition to allow it again */
+	trace_recursion_clear(TRACE_TRANSITION_BIT);
 
 	val |= 1 << bit;
 	current->trace_recursion = val;
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index b5e3496cf803..4738ad48a667 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -492,8 +492,13 @@ trace_selftest_function_recursion(void)
 	unregister_ftrace_function(&test_rec_probe);
 
 	ret = -1;
-	if (trace_selftest_recursion_cnt != 1) {
-		pr_cont("*callback not called once (%d)* ",
+	/*
+	 * Recursion allows for transitions between context,
+	 * and may call the callback twice.
+	 */
+	if (trace_selftest_recursion_cnt != 1 &&
+	    trace_selftest_recursion_cnt != 2) {
+		pr_cont("*callback not called once (or twice) (%d)* ",
 			trace_selftest_recursion_cnt);
 		goto out;
 	}
-- 
2.28.0



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

end of thread, other threads:[~2020-10-31 13:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-31 13:06 [for-linus][PATCH 0/3] tracing/ftrace: trace_printk buffer fix and ftrace recursion fixes Steven Rostedt
2020-10-31 13:06 ` [for-linus][PATCH 1/3] tracing: Fix out of bounds write in get_trace_buf Steven Rostedt
2020-10-31 13:06 ` [for-linus][PATCH 2/3] ftrace: Fix recursion check for NMI test Steven Rostedt
2020-10-31 13:06 ` [for-linus][PATCH 3/3] ftrace: Handle tracing when switching between context Steven Rostedt

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