From nobody Fri Sep 25 04:07:22 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E928D4D0CDB; Wed, 16 Sep 2026 18:30:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583435; cv=none; b=RB1KdGFKBOptgP97H7tictzliISA1teMOFTtgepsck+Dvtr+8ocxyhWU13eur5OGYcSdWhsTteWCZMhr3ZaZpOi8ts3msHJ0boXCbYQFJ9OADrcoNCLSVb4OIn2qmqnqA0xy8nW38ZHKlffxueNVfwmzwahFzOCwoXHHtjwDK8k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583435; c=relaxed/simple; bh=pCu8eDaR4ZlUXsDj7+6hsRc7dGWfoLSDSAAuOdPUByE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U0h1mNZRUP0a7GUY6TMCZlY671Cg3sYUqTqBVURVJg7xNBAz6M+X50Xo3fCIwgkTtPI7fzqz71UmPFs8Eh6zkIwHXWg1ei/Qn51jE5KKET5Op85kU8om9o4B5zvgkX/F0gotY6uRl0DaKeGxNfa8KQj0g2konUVnRONSVrY7MQs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.helo=mail.mainlining.org; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.helo=mail.mainlining.org From: Bradley Morgan To: Andrew Morton Cc: Petr Mladek , Jinchao Wang , Craig Lamparter , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, Bradley Morgan Subject: [PATCH v7 1/6] panic: fix redirect CPU race in panic_try_force_cpu() Date: Wed, 16 Sep 2026 18:29:52 +0000 Message-ID: <20260916182957.7788-2-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260916182957.7788-1-brads@mainlining.org> References: <20260916182957.7788-1-brads@mainlining.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 =3D A old_cpu =3D 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 =3D A) vsnprintf(msg) ... <-- NMI, nested panic --> panic() vpanic() panic_try_force_cpu() cmpxchg fails old_cpu =3D=3D 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=3D parameter to redirect p= anic to a specific CPU") Reported-by: Sashiko 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 Signed-off-by: Bradley Morgan --- kernel/panic.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/kernel/panic.c b/kernel/panic.c index 50715f14cf04..08072bfae422 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=3D boot par= ameter. * - * 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_l= ist args) return false; } =20 - /* 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(); =20 /* - * 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 !=3D this_cpu; =20 /* * Use dynamically allocated buffer if available, otherwise --=20 2.47.3 From nobody Fri Sep 25 04:07:22 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D0E2D495AC5; Wed, 16 Sep 2026 18:30:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583425; cv=none; b=hqxGjdYDHw9XSSDECaSwLbVc+R4rrboc3j1wKaSnQRb/jkClXPiybAjsMPsqypdpvsRD1ivx/Tx4DhWMtG2SG5Nz24PadoB5US/cGMepTWF781gM5ghLoRwigKxhIwF4i4zEzaxUPNLQpRf76PIjprRqfyV1jK80gxK1QGuI+ss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583425; c=relaxed/simple; bh=zKxViaEOvaJzgG6/gJIg519i1+dW6Lo821cxpbNjvLA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=X+sG8QZJhCk9l3ZdyGUs5kY/nQlfrRxFH02TRmtVclT79wXZyAWreOpxj+TaXooOeCewxEKlB0bTkFvVOHZ6P24ltG8XuLLwvDpwWe8GkRDHbSOF+fIcG5HAQjcBI/fm8VGaAN9NGB3Vdc6QGtMzj3a8qi1iz+nKj/P45ytZDqQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.helo=mail.mainlining.org; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.helo=mail.mainlining.org From: Bradley Morgan To: Andrew Morton Cc: Petr Mladek , Jinchao Wang , Craig Lamparter , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, Bradley Morgan Subject: [PATCH v7 2/6] panic: flatten nmi_panic control flow Date: Wed, 16 Sep 2026 18:29:53 +0000 Message-ID: <20260916182957.7788-3-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260916182957.7788-1-brads@mainlining.org> References: <20260916182957.7788-1-brads@mainlining.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" panic() is __noreturn, so the else after panic_try_start() is dead. Drop it so the force_cpu path can be added cleanly on top. Reviewed-by: Petr Mladek Signed-off-by: Bradley Morgan --- kernel/panic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/panic.c b/kernel/panic.c index 08072bfae422..5646d4fb82b7 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -517,7 +517,8 @@ void nmi_panic(struct pt_regs *regs, const char *msg) { if (panic_try_start()) panic("%s", msg); - else if (panic_on_other_cpu()) + + if (panic_on_other_cpu()) nmi_panic_self_stop(regs); } EXPORT_SYMBOL(nmi_panic); --=20 2.47.3 From nobody Fri Sep 25 04:07:22 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E899F4CEE71; Wed, 16 Sep 2026 18:30:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583435; cv=none; b=RknWeCROVQkUOMfudlPvSZqOOGva3Y4lsZCvsVy6ZnCwFKeQCtvBaQOqfCeqKCoz1nwn4kIAzRCvlx6puYplQCIgyisHYIRpiQ01v9WZpMCfUedqR0N7l+P0UstyF3AM1Lgf72RMSiFaBCgavCy02ke9JRf3EcfJMxzGzUTfZ0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583435; c=relaxed/simple; bh=hEm57w3U1srjrUXVgnFd75veH+GaeujpYLvRzttPDwo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FUwI5yDoD/0f+WyEOcxhnefLWMgIHNOtIIh8sAXXP41wA7HrBPpCmMLAZXKhiwm/td3UMdJWzzL3M0x1MkYDO413NGiCpp+i5+5rkeY+Qd5tbllCdXlx3NFkqWrV3LgXDzaY9K2Uxx5IVF+8QRLD01RwcmU+UEIJJEuqEZwVEoI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.helo=mail.mainlining.org; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.helo=mail.mainlining.org From: Bradley Morgan To: Andrew Morton Cc: Petr Mladek , Jinchao Wang , Craig Lamparter , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, Bradley Morgan Subject: [PATCH v7 3/6] panic: fix va_list reuse in panic_try_force_cpu() Date: Wed, 16 Sep 2026 18:29:54 +0000 Message-ID: <20260916182957.7788-4-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260916182957.7788-1-brads@mainlining.org> References: <20260916182957.7788-1-brads@mainlining.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" vsnprintf() consumes the caller's va_list. When the redirect fails, vpanic() reuses it for the panic message, which is undefined behavior. Use va_copy(). Fixes: 2e171ab29f91 ("panic: add panic_force_cpu=3D parameter to redirect p= anic to a specific CPU") Cc: stable@vger.kernel.org Reviewed-by: Petr Mladek Signed-off-by: Bradley Morgan --- kernel/panic.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/panic.c b/kernel/panic.c index 5646d4fb82b7..7388eb81a1c4 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -417,7 +417,12 @@ static bool panic_try_force_cpu(const char *fmt, va_li= st args) * fall back to static message for early boot panics or allocation failur= e. */ if (panic_force_buf) { - vsnprintf(panic_force_buf, PANIC_MSG_BUFSZ, fmt, args); + va_list ap; + + /* Do not consume args, the caller reuses it if we fail */ + va_copy(ap, args); + vsnprintf(panic_force_buf, PANIC_MSG_BUFSZ, fmt, ap); + va_end(ap); msg =3D panic_force_buf; } else { msg =3D "Redirected panic (buffer unavailable)"; --=20 2.47.3 From nobody Fri Sep 25 04:07:22 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 415424C2243; Wed, 16 Sep 2026 18:30:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583420; cv=none; b=X2gNEsiJP7U2HucVrdO9ug9oxpL5E6xBWtW5683zuU4sAIHHJXnvQB+WC0SfWu73Gj5uO9EqUrj1mBMaoPAcvxFWLzMwIM0BpXqlNqzF8fBTQ0rZX2KzLY24UtKZ553H2igncqp6NBprgYsfiUEZWUk8KQCLZn5EALEmkLNC47Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583420; c=relaxed/simple; bh=dyv4fdkjAz/+IS25pIkAfJLfB8i1e/864CKJn6kTrSo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NDX0c6z7ZwQP2fPN8DURq9KIHfhnrUazpruqDWnZdG4cZfZpZcd1bxIQskfX7UdY83JruihRpSPzWJfBy9S8vgOpaXHQYKAo8S1DBTj4onLxqqh/hEqNNLObw0fIrWRDtKbvfvS2TJFeareOdFDjXq38Ea3h+1X9KP5vS7FvCUA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.helo=mail.mainlining.org; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.helo=mail.mainlining.org From: Bradley Morgan To: Andrew Morton Cc: Petr Mladek , Jinchao Wang , Craig Lamparter , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, Bradley Morgan Subject: [PATCH v7 4/6] panic: restore variable arguments to nmi_panic() Date: Wed, 16 Sep 2026 18:29:55 +0000 Message-ID: <20260916182957.7788-5-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260916182957.7788-1-brads@mainlining.org> References: <20260916182957.7788-1-brads@mainlining.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" nmi_panic() used to accept variable arguments until commit ebc41f20d77f ("panic: change nmi_panic from macro to function") flattened it to a final message string. vpanic() did not exist back then, so the function had to format through panic("%s", msg). Bring the variable arguments back and format with vpanic() directly. The next patch makes nmi_panic() try the panic_force_cpu=3D redirect before claiming panic_cpu, which needs the arguments twice: once to format the message for the redirected CPU and once for vpanic() when no redirect happens. Passing a final string would lose that. No current caller passes a string with format specifiers. The closest one is hpwdt_pretimeout(), which builds panic_msg with hex_byte_pack() and has only two variants, both plain strings. But the new __printf() annotation on nmi_panic() would warn with -Wformat-security there because the buffer is passed directly as the format argument, so switch it to nmi_panic(regs, "%s", panic_msg). Suggested-by: Petr Mladek Signed-off-by: Bradley Morgan Reviewed-by: Petr Mladek --- drivers/watchdog/hpwdt.c | 2 +- include/linux/panic.h | 3 ++- kernel/panic.c | 10 ++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 8af1fad2de0b..78227d200afe 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -199,7 +199,7 @@ static int hpwdt_pretimeout(unsigned int ulReason, stru= ct pt_regs *regs) } =20 hex_byte_pack(panic_msg, nmistat); - nmi_panic(regs, panic_msg); + nmi_panic(regs, "%s", panic_msg); =20 return NMI_HANDLED; } diff --git a/include/linux/panic.h b/include/linux/panic.h index 98dd7dfd27de..17e61b61c45f 100644 --- a/include/linux/panic.h +++ b/include/linux/panic.h @@ -13,7 +13,8 @@ __printf(1, 2) void panic(const char *fmt, ...) __noreturn __cold; __printf(1, 0) void vpanic(const char *fmt, va_list args) __noreturn __cold; -void nmi_panic(struct pt_regs *regs, const char *msg); +__printf(2, 3) +void nmi_panic(struct pt_regs *regs, const char *fmt, ...); void check_panic_on_warn(const char *origin); extern void oops_enter(void); extern void oops_exit(void); diff --git a/kernel/panic.c b/kernel/panic.c index 7388eb81a1c4..e240ca06faab 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -518,13 +518,19 @@ EXPORT_SYMBOL(panic_on_other_cpu); * nmi_panic_self_stop() which can provide architecture dependent code such * as saving register state for crash dump. */ -void nmi_panic(struct pt_regs *regs, const char *msg) +void nmi_panic(struct pt_regs *regs, const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + if (panic_try_start()) - panic("%s", msg); + vpanic(fmt, args); =20 if (panic_on_other_cpu()) nmi_panic_self_stop(regs); + + va_end(args); } EXPORT_SYMBOL(nmi_panic); =20 --=20 2.47.3 From nobody Fri Sep 25 04:07:22 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E8D7C4D37CB; Wed, 16 Sep 2026 18:30:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583434; cv=none; b=ngr26X7QYbfOpVoTU3JB0dTdFSh/Y4uTIcQffi7r3K5SIUAI048Sbylst22PF/IWSJWILhMRlkhgYMLo/rq260grPt2wI2N67SarT59Ay3r61c+bj2XsIJk22wgzIYgeLvDZdCsWns/1ubGP3HxLDvY7yZJTrveQsT0F2GsovMo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583434; c=relaxed/simple; bh=1L0EWxkDhNvr8iX44QENpR0+tXTy2IOKo6E6J3CPJHk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QTrJrkIal12knp2CUwkBUUExBS5gcBwPK1peuNc+88BzcdpFUoOlgmtmuUK2dH7RaziY7nrMBXt4av8x6OsFHqI7x78RjVPWj+ZRmHjhidfv/b81GYKxtlV/h7rXhrv7O3qXmkS4ojvImcnPYneleUgnzG+t19t45R5E5T11pes= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.helo=mail.mainlining.org; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.helo=mail.mainlining.org From: Bradley Morgan To: Andrew Morton Cc: Petr Mladek , Jinchao Wang , Craig Lamparter , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, Bradley Morgan Subject: [PATCH v7 5/6] panic: allow force_cpu redirect from an NMI Date: Wed, 16 Sep 2026 18:29:56 +0000 Message-ID: <20260916182957.7788-6-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260916182957.7788-1-brads@mainlining.org> References: <20260916182957.7788-1-brads@mainlining.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" nmi_panic() claims panic_cpu via panic_try_start() before calling panic(). When the panic later reaches panic_try_force_cpu(), the panic_in_progress() check sees panic_cpu set and refuses to redirect. The crash kernel runs on the CPU that took the NMI instead of the CPU requested with panic_force_cpu=3D: nmi_panic() panic_try_start() wins, panic_cpu =3D X panic("%s", msg) vpanic() panic_try_force_cpu() panic_in_progress() true, panic_cpu is X return false redirect bypassed panic_try_start() already won __crash_kexec() on X, not the requested CPU Try the redirect before claiming panic_cpu instead, as suggested by Petr Mladek. nmi_panic() now calls panic_try_force_cpu() first and claims panic_cpu only when no redirect happened. The requested CPU claims panic_cpu itself when it runs panic(), so panic_cpu does not need to be handed off. panic_try_force_cpu() copies the arguments before formatting (patch 3), so nmi_panic() can pass them to vpanic() again when no redirect happens. The redirect IPI is sent with smp_call_function_single_async(), which is not guaranteed to work from NMI context. Treat it as best effort. It is worth the risk because the redirection is only used when the crash kernel would not work on the panicking CPU anyway. Keep returning when the panic is already running on this CPU. A nested NMI, for example with unknown_nmi_panic while this CPU is inside panic(), must return and let the interrupted panic() continue instead of parking the CPU in nmi_panic_self_stop(). Mark the redirecting CPU offline before stopping it, like vpanic() does, so that panic_other_cpus_shutdown() on the target CPU does not wait for it. Fixes: 2e171ab29f91 ("panic: add panic_force_cpu=3D parameter to redirect p= anic to a specific CPU") Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260708164312.19044-1-include@grrlz= .net Cc: stable@vger.kernel.org Reviewed-by: Petr Mladek Signed-off-by: Bradley Morgan --- kernel/panic.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/kernel/panic.c b/kernel/panic.c index e240ca06faab..29c981926f5f 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -513,10 +513,11 @@ bool panic_on_other_cpu(void) EXPORT_SYMBOL(panic_on_other_cpu); =20 /* - * A variant of panic() called from NMI context. We return if we've already - * panicked on this CPU. If another CPU already panicked, loop in - * nmi_panic_self_stop() which can provide architecture dependent code such - * as saving register state for crash dump. + * A variant of panic() called from NMI context. The panic is first + * redirected to the CPU requested via panic_force_cpu=3D, when configured. + * We return if we've already panicked on this CPU. If another CPU already + * panicked, loop in nmi_panic_self_stop() which can provide architecture + * dependent code for saving register state for crash dump. */ void nmi_panic(struct pt_regs *regs, const char *fmt, ...) { @@ -524,6 +525,16 @@ void nmi_panic(struct pt_regs *regs, const char *fmt, = ...) =20 va_start(args, fmt); =20 + /* Try to redirect to the requested CPU before claiming panic_cpu. */ + if (panic_try_force_cpu(fmt, args)) { + /* + * Mark ourselves offline so panic_other_cpus_shutdown() won't + * wait for us on architectures that check num_online_cpus(). + */ + set_cpu_online(raw_smp_processor_id(), false); + nmi_panic_self_stop(regs); + } + if (panic_try_start()) vpanic(fmt, args); =20 --=20 2.47.3 From nobody Fri Sep 25 04:07:22 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5150D49F10E; Wed, 16 Sep 2026 18:30:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583443; cv=none; b=SIBoMObit0QNK9aqfJJYqper8iD0vbu3ijLi5SHuzBa3v+7+UY+f83PdYuhbbWjO6nJJ0u8/st+ec6jXH7qksJlf9hwC5LXElA4p91832radWCBOXyQrtM7zi/F24ToaAIAo7TQi80e0xb2ZwqIt9Jb9tr1sjsV6zefT0uVW61Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789583443; c=relaxed/simple; bh=HYrnP/UY/JSQyUQ/S+6h6FZeJGu4BlLn4CGWcriONE0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DVZP6MyJzpL4CBKOO+flPhyTmiG2BVF3eWYlvkPB036AiFHwSa1y1J6tRZmXly95nt/y/LnMDoTeQZkS5kgntKp7qDSilbFf47BnMcjT4rEFDyOlwCvrIiCE344eYaB7rc19r9vfyrhd6JW3pGhCoR77gtUcwM/y/n0hDi0lCuo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.helo=mail.mainlining.org; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.helo=mail.mainlining.org From: Bradley Morgan To: Andrew Morton Cc: Petr Mladek , Jinchao Wang , Craig Lamparter , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, Bradley Morgan Subject: [PATCH v7 6/6] panic: kill the "buffer unavailable" redirect fallback Date: Wed, 16 Sep 2026 18:29:57 +0000 Message-ID: <20260916182957.7788-7-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260916182957.7788-1-brads@mainlining.org> References: <20260916182957.7788-1-brads@mainlining.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The redirect buffer is a disgusting terrible hack. panic_force_buf is kmalloc'ed in a late_initcall, and until then the redirect delivers this as the panic message: Redirected panic (buffer unavailable) The whole point of the redirect is to hand the panic message to the target CPU, so the crash kernel boots knowing it panicked and not why. And that window is the entire boot, from the early_param to the late_initcall, which is exactly when you most want the message. Make it a static 1KB buffer and kill the initcall. The cost is 1KB of .bss in SMP crash dump builds, and it is only ever touched when panic_force_cpu=3D is set anyway. The local msg variable is gone too, the buffer goes directly to panic_smp_redirect_cpu(). Suggested-by: Petr Mladek Signed-off-by: Bradley Morgan Reviewed-by: Petr Mladek --- kernel/panic.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/kernel/panic.c b/kernel/panic.c index 29c981926f5f..170744163fc2 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -307,7 +307,7 @@ atomic_t panic_cpu =3D ATOMIC_INIT(PANIC_CPU_INVALID); atomic_t panic_redirect_cpu =3D ATOMIC_INIT(PANIC_CPU_INVALID); =20 #if defined(CONFIG_SMP) && defined(CONFIG_CRASH_DUMP) -static char *panic_force_buf; +static char panic_force_buf[PANIC_MSG_BUFSZ]; =20 static int __init panic_force_cpu_setup(char *str) { @@ -326,17 +326,6 @@ static int __init panic_force_cpu_setup(char *str) } early_param("panic_force_cpu", panic_force_cpu_setup); =20 -static int __init panic_force_cpu_late_init(void) -{ - if (panic_force_cpu < 0) - return 0; - - panic_force_buf =3D kmalloc(PANIC_MSG_BUFSZ, GFP_KERNEL); - - return 0; -} -late_initcall(panic_force_cpu_late_init); - static void do_panic_on_target_cpu(void *info) { panic("%s", (char *)info); @@ -380,7 +369,7 @@ static bool panic_try_force_cpu(const char *fmt, va_lis= t args) { int this_cpu =3D raw_smp_processor_id(); int old_cpu =3D PANIC_CPU_INVALID; - const char *msg; + va_list ap; =20 /* Feature not enabled via boot parameter */ if (panic_force_cpu < 0) @@ -413,20 +402,11 @@ static bool panic_try_force_cpu(const char *fmt, va_l= ist args) return old_cpu !=3D this_cpu; =20 /* - * Use dynamically allocated buffer if available, otherwise - * fall back to static message for early boot panics or allocation failur= e. + * Do not consume args, the caller reuses them if we fail. */ - if (panic_force_buf) { - va_list ap; - - /* Do not consume args, the caller reuses it if we fail */ - va_copy(ap, args); - vsnprintf(panic_force_buf, PANIC_MSG_BUFSZ, fmt, ap); - va_end(ap); - msg =3D panic_force_buf; - } else { - msg =3D "Redirected panic (buffer unavailable)"; - } + va_copy(ap, args); + vsnprintf(panic_force_buf, PANIC_MSG_BUFSZ, fmt, ap); + va_end(ap); =20 console_verbose(); bust_spinlocks(1); @@ -441,7 +421,7 @@ static bool panic_try_force_cpu(const char *fmt, va_lis= t args) dump_stack(); } =20 - if (panic_smp_redirect_cpu(panic_force_cpu, (void *)msg) !=3D 0) { + if (panic_smp_redirect_cpu(panic_force_cpu, panic_force_buf) !=3D 0) { atomic_set(&panic_redirect_cpu, PANIC_CPU_INVALID); pr_warn("panic: failed to redirect to CPU %d, continuing on CPU %d\n", panic_force_cpu, this_cpu); --=20 2.47.3