summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJohn Ogness <john.ogness@linutronix.de>2024-02-07 14:41:03 +0100
committerPetr Mladek <pmladek@suse.com>2024-02-07 17:23:19 +0100
commit7412dc6d55eed6b76180e40ac3601412ebde29bd (patch)
tree3cb98e9f442a2c06d0d8005248a3a9841730d5e7 /lib
parentpanic: Flush kernel log buffer at the end (diff)
downloadlinux-7412dc6d55eed6b76180e40ac3601412ebde29bd.tar.xz
linux-7412dc6d55eed6b76180e40ac3601412ebde29bd.zip
dump_stack: Do not get cpu_sync for panic CPU
dump_stack() is called in panic(). If for some reason another CPU is holding the printk_cpu_sync and is unable to release it, the panic CPU will be unable to continue and print the stacktrace. Since non-panic CPUs are not allowed to store new printk messages anyway, there is no need to synchronize the stacktrace output in a panic situation. For the panic CPU, do not get the printk_cpu_sync because it is not needed and avoids a potential deadlock scenario in panic(). Link: https://lore.kernel.org/lkml/ZcIGKU8sxti38Kok@alley Signed-off-by: John Ogness <john.ogness@linutronix.de> Reviewed-by: Petr Mladek <pmladek@suse.com> Link: https://lore.kernel.org/r/20240207134103.1357162-15-john.ogness@linutronix.de Signed-off-by: Petr Mladek <pmladek@suse.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/dump_stack.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/lib/dump_stack.c b/lib/dump_stack.c
index 83471e81501a..222c6d6c8281 100644
--- a/lib/dump_stack.c
+++ b/lib/dump_stack.c
@@ -96,15 +96,25 @@ static void __dump_stack(const char *log_lvl)
*/
asmlinkage __visible void dump_stack_lvl(const char *log_lvl)
{
+ bool in_panic = this_cpu_in_panic();
unsigned long flags;
/*
* Permit this cpu to perform nested stack dumps while serialising
- * against other CPUs
+ * against other CPUs, unless this CPU is in panic.
+ *
+ * When in panic, non-panic CPUs are not permitted to store new
+ * printk messages so there is no need to synchronize the output.
+ * This avoids potential deadlock in panic() if another CPU is
+ * holding and unable to release the printk_cpu_sync.
*/
- printk_cpu_sync_get_irqsave(flags);
+ if (!in_panic)
+ printk_cpu_sync_get_irqsave(flags);
+
__dump_stack(log_lvl);
- printk_cpu_sync_put_irqrestore(flags);
+
+ if (!in_panic)
+ printk_cpu_sync_put_irqrestore(flags);
}
EXPORT_SYMBOL(dump_stack_lvl);