From: Greg Kroah-Hartman Date: Sun, 8 Nov 2020 19:12:16 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.4.242~31 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f965f6ab6c989e6ee978c062528eaad53af69d9d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: ftrace-fix-recursion-check-for-nmi-test.patch ftrace-handle-tracing-when-switching-between-context.patch tracing-fix-out-of-bounds-write-in-get_trace_buf.patch --- diff --git a/queue-4.9/ftrace-fix-recursion-check-for-nmi-test.patch b/queue-4.9/ftrace-fix-recursion-check-for-nmi-test.patch new file mode 100644 index 00000000000..41785900e2c --- /dev/null +++ b/queue-4.9/ftrace-fix-recursion-check-for-nmi-test.patch @@ -0,0 +1,49 @@ +From ee11b93f95eabdf8198edd4668bf9102e7248270 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Thu, 29 Oct 2020 17:31:45 -0400 +Subject: ftrace: Fix recursion check for NMI test + +From: Steven Rostedt (VMware) + +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) +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/trace.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -542,7 +542,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) +@@ -552,6 +552,7 @@ static __always_inline void trace_clear_ + if (!bit) + return; + ++ bit--; + bit = 1 << bit; + val &= ~bit; + diff --git a/queue-4.9/ftrace-handle-tracing-when-switching-between-context.patch b/queue-4.9/ftrace-handle-tracing-when-switching-between-context.patch new file mode 100644 index 00000000000..330a98aa210 --- /dev/null +++ b/queue-4.9/ftrace-handle-tracing-when-switching-between-context.patch @@ -0,0 +1,92 @@ +From 726b3d3f141fba6f841d715fc4d8a4a84f02c02a Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Thu, 29 Oct 2020 19:35:08 -0400 +Subject: ftrace: Handle tracing when switching between context + +From: Steven Rostedt (VMware) + +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) +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -491,6 +491,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) +@@ -535,8 +541,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; + } diff --git a/queue-4.9/series b/queue-4.9/series index a976ee410b7..b37a0e7458b 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -96,3 +96,6 @@ 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 kthread_worker-prevent-queuing-delayed-work-from-timer_fn-when-it-is-being-canceled.patch +ftrace-fix-recursion-check-for-nmi-test.patch +ftrace-handle-tracing-when-switching-between-context.patch +tracing-fix-out-of-bounds-write-in-get_trace_buf.patch diff --git a/queue-4.9/tracing-fix-out-of-bounds-write-in-get_trace_buf.patch b/queue-4.9/tracing-fix-out-of-bounds-write-in-get_trace_buf.patch new file mode 100644 index 00000000000..2d0df40f7b0 --- /dev/null +++ b/queue-4.9/tracing-fix-out-of-bounds-write-in-get_trace_buf.patch @@ -0,0 +1,38 @@ +From c1acb4ac1a892cf08d27efcb964ad281728b0545 Mon Sep 17 00:00:00 2001 +From: Qiujun Huang +Date: Fri, 30 Oct 2020 00:19:05 +0800 +Subject: tracing: Fix out of bounds write in get_trace_buf + +From: Qiujun Huang + +commit c1acb4ac1a892cf08d27efcb964ad281728b0545 upstream. + +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 +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/trace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -2382,7 +2382,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)