Skip to content

Commit d515070

Browse files
brenns10pmladek
authored andcommitted
printk: disable optimistic spin during panic
A CPU executing with console lock spinning enabled might be halted during a panic. Before the panicking CPU calls console_flush_on_panic(), it may call console_trylock(), which attempts to optimistically spin, deadlocking the panic CPU: CPU 0 (panic CPU) CPU 1 ----------------- ------ printk() { vprintk_func() { vprintk_default() { vprintk_emit() { console_unlock() { console_lock_spinning_enable(); ... printing to console ... panic() { crash_smp_send_stop() { NMI -------------------> HALT } atomic_notifier_call_chain() { printk() { ... console_trylock_spinnning() { // optimistic spin infinitely This hang during panic can be induced when a kdump kernel is loaded, and crash_kexec_post_notifiers=1 is present on the kernel command line. The following script which concurrently writes to /dev/kmsg, and triggers a panic, can result in this hang: #!/bin/bash date # 991 chars (based on log buffer size): chars="$(printf 'a%.0s' {1..991})" while :; do echo $chars > /dev/kmsg done & echo c > /proc/sysrq-trigger & date exit To avoid this deadlock, ensure that console_trylock_spinning() does not allow spinning once a panic has begun. Fixes: dbdda84 ("printk: Add console owner and waiter logic to load balance console writes") Suggested-by: Petr Mladek <pmladek@suse.com> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com> Reviewed-by: Petr Mladek <pmladek@suse.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Signed-off-by: Petr Mladek <pmladek@suse.com> Link: https://lore.kernel.org/r/20220202171821.179394-3-stephen.s.brennan@oracle.com
1 parent 7749861 commit d515070

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

kernel/printk/printk.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,6 +1847,16 @@ static int console_trylock_spinning(void)
18471847
if (console_trylock())
18481848
return 1;
18491849

1850+
/*
1851+
* It's unsafe to spin once a panic has begun. If we are the
1852+
* panic CPU, we may have already halted the owner of the
1853+
* console_sem. If we are not the panic CPU, then we should
1854+
* avoid taking console_sem, so the panic CPU has a better
1855+
* chance of cleanly acquiring it later.
1856+
*/
1857+
if (panic_in_progress())
1858+
return 0;
1859+
18501860
printk_safe_enter_irqsave(flags);
18511861

18521862
raw_spin_lock(&console_owner_lock);

0 commit comments

Comments
 (0)