From ed9e4c1ff15d5b935f467811541ca0aa6e49c5d0 Mon Sep 17 00:00:00 2001 From: Bradley Morgan Date: Wed, 16 Sep 2026 18:29:55 +0000 Subject: [PATCH] panic: restore variable arguments to nmi_panic() 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= redirect before claiming panic_cpu. panic_try_force_cpu() needs to print the message but it is used also by panic() which accepts variable argument list. The string could be formatted only when a CPU gets assigned to process the redirection. Otherwise, there might be a race when writing to the `panic_force_buf`. 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). [pmladek@suse.com: changelog fix] Link: https://lore.kernel.org/arJxFybmtD7OBIcL@pathway.suse.cz Link: https://lore.kernel.org/20260916182957.7788-5-brads@mainlining.org Signed-off-by: Bradley Morgan Signed-off-by: Andrew Morton Suggested-by: Petr Mladek Reviewed-by: Petr Mladek Cc: Guenetr Roeck Cc: Sashiko Cc: Wang Jinchao Cc: Wim Van Sebroeck Cc: --- 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, struct pt_regs *regs) } hex_byte_pack(panic_msg, nmistat); - nmi_panic(regs, panic_msg); + nmi_panic(regs, "%s", panic_msg); 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); if (panic_on_other_cpu()) nmi_panic_self_stop(regs); + + va_end(args); } EXPORT_SYMBOL(nmi_panic);