]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Nov 2020 19:10:56 +0000 (20:10 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Nov 2020 19:10:56 +0000 (20:10 +0100)
added patches:
ftrace-fix-recursion-check-for-nmi-test.patch
ftrace-handle-tracing-when-switching-between-context.patch

queue-4.4/ftrace-fix-recursion-check-for-nmi-test.patch [new file with mode: 0644]
queue-4.4/ftrace-handle-tracing-when-switching-between-context.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/ftrace-fix-recursion-check-for-nmi-test.patch b/queue-4.4/ftrace-fix-recursion-check-for-nmi-test.patch
new file mode 100644 (file)
index 0000000..a96fccf
--- /dev/null
@@ -0,0 +1,49 @@
+From ee11b93f95eabdf8198edd4668bf9102e7248270 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
+Date: Thu, 29 Oct 2020 17:31:45 -0400
+Subject: ftrace: Fix recursion check for NMI test
+
+From: Steven Rostedt (VMware) <rostedt@goodmis.org>
+
+commit ee11b93f95eabdf8198edd4668bf9102e7248270 upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/trace/trace.h |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/trace/trace.h
++++ b/kernel/trace/trace.h
+@@ -529,7 +529,7 @@ static __always_inline int trace_test_an
+       current->trace_recursion = val;
+       barrier();
+-      return bit;
++      return bit + 1;
+ }
+ static __always_inline void trace_clear_recursion(int bit)
+@@ -539,6 +539,7 @@ static __always_inline void trace_clear_
+       if (!bit)
+               return;
++      bit--;
+       bit = 1 << bit;
+       val &= ~bit;
diff --git a/queue-4.4/ftrace-handle-tracing-when-switching-between-context.patch b/queue-4.4/ftrace-handle-tracing-when-switching-between-context.patch
new file mode 100644 (file)
index 0000000..3c7a501
--- /dev/null
@@ -0,0 +1,92 @@
+From 726b3d3f141fba6f841d715fc4d8a4a84f02c02a Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
+Date: Thu, 29 Oct 2020 19:35:08 -0400
+Subject: ftrace: Handle tracing when switching between context
+
+From: Steven Rostedt (VMware) <rostedt@goodmis.org>
+
+commit 726b3d3f141fba6f841d715fc4d8a4a84f02c02a upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/trace/trace.h          |   23 +++++++++++++++++++++--
+ kernel/trace/trace_selftest.c |    9 +++++++--
+ 2 files changed, 28 insertions(+), 4 deletions(-)
+
+--- a/kernel/trace/trace.h
++++ b/kernel/trace/trace.h
+@@ -478,6 +478,12 @@ enum {
+  * can only be modified by current, we can reuse trace_recursion.
+  */
+       TRACE_IRQ_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)
+@@ -522,8 +528,21 @@ static __always_inline int trace_test_an
+               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;
+--- a/kernel/trace/trace_selftest.c
++++ b/kernel/trace/trace_selftest.c
+@@ -490,8 +490,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;
+       }
index b4a8a8a63596a4dd538dea9cd15285c332882fe9..4b9377d7e36598927b5089a4f9c6dc41896edecd 100644 (file)
@@ -67,3 +67,5 @@ gianfar-replace-skb_realloc_headroom-with-skb_cow_head-for-ptp.patch
 gianfar-account-for-tx-ptp-timestamp-in-the-skb-headroom.patch
 fonts-replace-discarded-const-qualifier.patch
 alsa-usb-audio-add-implicit-feedback-quirk-for-qu-16.patch
+ftrace-fix-recursion-check-for-nmi-test.patch
+ftrace-handle-tracing-when-switching-between-context.patch