From: Bradley Morgan <include@grrlz.net>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Petr Mladek <pmladek@suse.com>,
Jinchao Wang <wangjinchao600@gmail.com>,
Feng Tang <feng.tang@linux.alibaba.com>,
Rio <rioo.tsukatsukii@gmail.com>,
Pnina Feder <pnina.feder@mobileye.com>,
Petr Pavlu <petr.pavlu@suse.com>,
Sergey Senozhatsky <senozhatsky@chromium.org>,
linux-kernel@vger.kernel.org, Bradley Morgan <include@grrlz.net>,
Sashiko <sashiko-bot@kernel.org>,
stable@vger.kernel.org
Subject: [PATCH v6 1/6] panic: fix redirect CPU race in panic_try_force_cpu()
Date: Tue, 18 Aug 2026 16:38:01 +0000 [thread overview]
Message-ID: <20260818163806.17460-2-include@grrlz.net> (raw)
In-Reply-To: <20260818163806.17460-1-include@grrlz.net>
The cmpxchg() in panic_try_force_cpu() makes sure that only one CPU
tries to redirect panic() to the requested CPU. It is similar to the
cmpxchg() in panic_try_start() which makes sure that only one CPU does
the panic(). In both situations, only the winner of cmpxchg() should
proceed further. Other CPUs should go offline.
There is a bug because the cmpxchg loser returns false and falls through
into vpanic(). Two non-target CPUs A and B panic, the requested CPU is C:
cpu A cpu B
---------- ----------
panic() panic()
vpanic() vpanic()
panic_try_force_cpu() panic_try_force_cpu()
cmpxchg wins cmpxchg fails
redirect = A old_cpu = A
IPI -> C return false <- BUG
return true panic_try_start() wins
panic_smp_self_stop() __crash_kexec() on B
(A stops) (target C bypassed)
The loser must stop, not fall through. It cannot just return true,
though. A CPU that already won the redirect cmpxchg can reenter
panic_try_force_cpu() on the same CPU, for example a nested NMI during
the message formatting, before the IPI is sent:
cpu A (1st) cpu A (nested)
---------- ----------
panic()
vpanic()
panic_try_force_cpu()
cmpxchg wins (redirect = A)
vsnprintf(msg) ...
<-- NMI, nested panic -->
panic()
vpanic()
panic_try_force_cpu()
cmpxchg fails
old_cpu == A (this CPU)
return true <- would halt
panic_smp_self_stop()
(IPI never sent, panic abandoned)
Check old_cpu against this_cpu so a second call from the same CPU
returns false and falls through to panic_try_start() instead.
Also fix the panic_in_progress() check. We must not redirect when
panic_cpu is already assigned. Return true to stop when the panic is on
another CPU, false to proceed when it is this one.
Update the panic_try_force_cpu() doc comment for the new return value
semantics.
Fixes: 2e171ab29f91 ("panic: add panic_force_cpu= parameter to redirect panic to a specific CPU")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260705164123.18746-1-include@grrlz.net
Closes: https://sashiko.dev/#/patchset/20260707172252.4842-1-include@grrlz.net
Cc: stable@vger.kernel.org
Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Bradley Morgan <include@grrlz.net>
---
kernel/panic.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/kernel/panic.c b/kernel/panic.c
index 213725b612aa..010b331658b6 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -371,8 +371,9 @@ int __weak panic_smp_redirect_cpu(int target_cpu, void *msg)
* for the crash kernel to function correctly. This function redirects
* panic handling to the CPU specified via the panic_force_cpu= boot parameter.
*
- * Returns false if panic should proceed on current CPU.
- * Returns true if panic was redirected.
+ * Returns true when this CPU must stop: the panic was redirected or is
+ * already running on another CPU.
+ * Returns false when panic() should proceed on this CPU.
*/
__printf(1, 0)
static bool panic_try_force_cpu(const char *fmt, va_list args)
@@ -396,16 +397,20 @@ static bool panic_try_force_cpu(const char *fmt, va_list args)
return false;
}
- /* Another panic already in progress */
+ /*
+ * Don't redirect when a panic is already in progress. Stop this
+ * CPU when it's another one, proceed when it's this one.
+ */
if (panic_in_progress())
- return false;
+ return panic_on_other_cpu();
/*
- * Only one CPU can do the redirect. Use atomic cmpxchg to ensure
- * we don't race with another CPU also trying to redirect.
+ * Only one CPU can do the redirection. Others should go offline.
+ * Continue with panic() when we already tried the redirection
+ * from this CPU before, for example via nmi_panic().
*/
if (!atomic_try_cmpxchg(&panic_redirect_cpu, &old_cpu, this_cpu))
- return false;
+ return old_cpu != this_cpu;
/*
* Use dynamically allocated buffer if available, otherwise
--
2.47.3
next prev parent reply other threads:[~2026-08-18 16:38 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 16:38 [PATCH v6 0/6] panic: fix panic_force_cpu= redirect races and NMI bypass Bradley Morgan
2026-08-18 16:38 ` Bradley Morgan [this message]
2026-08-18 16:38 ` [PATCH v6 2/6] panic: flatten nmi_panic control flow Bradley Morgan
2026-08-18 16:38 ` [PATCH v6 3/6] panic: fix va_list reuse in panic_try_force_cpu() Bradley Morgan
2026-08-18 16:38 ` [PATCH v6 4/6] panic: restore variable arguments to nmi_panic() Bradley Morgan
2026-08-18 16:38 ` [PATCH v6 5/6] panic: allow force_cpu redirect from an NMI Bradley Morgan
2026-08-18 16:38 ` [PATCH v6 6/6] panic: kill the "buffer unavailable" redirect fallback Bradley Morgan
2026-08-18 18:41 ` [PATCH v6 0/6] panic: fix panic_force_cpu= redirect races and NMI bypass Andrew Morton
2026-08-18 18:45 ` Bradley Morgan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260818163806.17460-2-include@grrlz.net \
--to=include@grrlz.net \
--cc=akpm@linux-foundation.org \
--cc=feng.tang@linux.alibaba.com \
--cc=linux-kernel@vger.kernel.org \
--cc=petr.pavlu@suse.com \
--cc=pmladek@suse.com \
--cc=pnina.feder@mobileye.com \
--cc=rioo.tsukatsukii@gmail.com \
--cc=sashiko-bot@kernel.org \
--cc=senozhatsky@chromium.org \
--cc=stable@vger.kernel.org \
--cc=wangjinchao600@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®