From: Greg Kroah-Hartman Date: Sun, 8 Nov 2020 19:12:48 +0000 (+0100) Subject: 4.19-stable patches X-Git-Tag: v4.4.242~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4a0099918069ee34770f4b982591a79262ce750e;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: ftrace-fix-recursion-check-for-nmi-test.patch ftrace-handle-tracing-when-switching-between-context.patch futex-handle-transient-ownerless-rtmutex-state-correctly.patch tracing-fix-out-of-bounds-write-in-get_trace_buf.patch --- diff --git a/queue-4.19/ftrace-fix-recursion-check-for-nmi-test.patch b/queue-4.19/ftrace-fix-recursion-check-for-nmi-test.patch new file mode 100644 index 00000000000..ab34e680793 --- /dev/null +++ b/queue-4.19/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 +@@ -595,7 +595,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) +@@ -605,6 +605,7 @@ static __always_inline void trace_clear_ + if (!bit) + return; + ++ bit--; + bit = 1 << bit; + val &= ~bit; + diff --git a/queue-4.19/ftrace-handle-tracing-when-switching-between-context.patch b/queue-4.19/ftrace-handle-tracing-when-switching-between-context.patch new file mode 100644 index 00000000000..d4a27df51c4 --- /dev/null +++ b/queue-4.19/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 +@@ -534,6 +534,12 @@ enum { + + TRACE_GRAPH_DEPTH_START_BIT, + TRACE_GRAPH_DEPTH_END_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) +@@ -588,8 +594,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 +@@ -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; + } diff --git a/queue-4.19/futex-handle-transient-ownerless-rtmutex-state-correctly.patch b/queue-4.19/futex-handle-transient-ownerless-rtmutex-state-correctly.patch new file mode 100644 index 00000000000..7bb9e57ecea --- /dev/null +++ b/queue-4.19/futex-handle-transient-ownerless-rtmutex-state-correctly.patch @@ -0,0 +1,80 @@ +From 9f5d1c336a10c0d24e83e40b4c1b9539f7dba627 Mon Sep 17 00:00:00 2001 +From: Mike Galbraith +Date: Wed, 4 Nov 2020 16:12:44 +0100 +Subject: futex: Handle transient "ownerless" rtmutex state correctly + +From: Mike Galbraith + +commit 9f5d1c336a10c0d24e83e40b4c1b9539f7dba627 upstream. + +Gratian managed to trigger the BUG_ON(!newowner) in fixup_pi_state_owner(). +This is one possible chain of events leading to this: + +Task Prio Operation +T1 120 lock(F) +T2 120 lock(F) -> blocks (top waiter) +T3 50 (RT) lock(F) -> boosts T1 and blocks (new top waiter) +XX timeout/ -> wakes T2 + signal +T1 50 unlock(F) -> wakes T3 (rtmutex->owner == NULL, waiter bit is set) +T2 120 cleanup -> try_to_take_mutex() fails because T3 is the top waiter + and the lower priority T2 cannot steal the lock. + -> fixup_pi_state_owner() sees newowner == NULL -> BUG_ON() + +The comment states that this is invalid and rt_mutex_real_owner() must +return a non NULL owner when the trylock failed, but in case of a queued +and woken up waiter rt_mutex_real_owner() == NULL is a valid transient +state. The higher priority waiter has simply not yet managed to take over +the rtmutex. + +The BUG_ON() is therefore wrong and this is just another retry condition in +fixup_pi_state_owner(). + +Drop the locks, so that T3 can make progress, and then try the fixup again. + +Gratian provided a great analysis, traces and a reproducer. The analysis is +to the point, but it confused the hell out of that tglx dude who had to +page in all the futex horrors again. Condensed version is above. + +[ tglx: Wrote comment and changelog ] + +Fixes: c1e2f0eaf015 ("futex: Avoid violating the 10th rule of futex") +Reported-by: Gratian Crisan +Signed-off-by: Mike Galbraith +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/87a6w6x7bb.fsf@ni.com +Link: https://lore.kernel.org/r/87sg9pkvf7.fsf@nanos.tec.linutronix.de +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/futex.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -2417,10 +2417,22 @@ retry: + } + + /* +- * Since we just failed the trylock; there must be an owner. ++ * The trylock just failed, so either there is an owner or ++ * there is a higher priority waiter than this one. + */ + newowner = rt_mutex_owner(&pi_state->pi_mutex); +- BUG_ON(!newowner); ++ /* ++ * If the higher priority waiter has not yet taken over the ++ * rtmutex then newowner is NULL. We can't return here with ++ * that state because it's inconsistent vs. the user space ++ * state. So drop the locks and try again. It's a valid ++ * situation and not any different from the other retry ++ * conditions. ++ */ ++ if (unlikely(!newowner)) { ++ err = -EAGAIN; ++ goto handle_err; ++ } + } else { + WARN_ON_ONCE(argowner != current); + if (oldowner == current) { diff --git a/queue-4.19/series b/queue-4.19/series index ce6c6097ad1..69e07a96633 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -39,3 +39,7 @@ kthread_worker-prevent-queuing-delayed-work-from-timer_fn-when-it-is-being-cance mm-always-have-io_remap_pfn_range-set-pgprot_decrypted.patch gfs2-wake-up-when-sd_glock_disposal-becomes-zero.patch ring-buffer-fix-recursion-protection-transitions-between-interrupt-context.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 +futex-handle-transient-ownerless-rtmutex-state-correctly.patch diff --git a/queue-4.19/tracing-fix-out-of-bounds-write-in-get_trace_buf.patch b/queue-4.19/tracing-fix-out-of-bounds-write-in-get_trace_buf.patch new file mode 100644 index 00000000000..4015b509971 --- /dev/null +++ b/queue-4.19/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 +@@ -2819,7 +2819,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)