[RFC] tty/vt: Prevent re-entering vt_console_print() in panic() without spin_lock
From: Petr Mladek
Date: Wed Jan 21 2026 - 04:47:15 EST
The commit b0940003f25dd ("vt: bitlock fix") replaced a simple bit
operation with spin_lock() to get proper memory barriers.
But the code called under this lock calls console_conditional_schedule()
which calls cond_resched() when console_sem() has been acquired
in a preemptive context using console_lock(). Note that the semaphore
can be taken also in an atomic context using console_trylock()
which is used by printk().
One solution would be to remove console_conditional_schedule().
It does not have any effect in the printk() code path anyway.
But the affected VT code is not used just by printk(). And
the cond_resched() calls were likely added for a reason.
Instead, convert the spin_lock back to an atomic operation with
proper barriers. The only purpose of the lock is to prevent
a concurrent access to the guarded code in
console_flush_on_panic() where console_lock() is ignored.
Using a full featured spin_trylock, just to get memory barriers
right, looks like an overkill anyway.
Fixes: b0940003f25dd ("vt: bitlock fix")
Closes: https://lore.kernel.org/all/20260114145955.d924Z-zu@xxxxxxxxxxxxx/
Signed-off-by: Petr Mladek <pmladek@xxxxxxxx>
---
drivers/tty/vt/vt.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 59b4b5e126ba..5be64d1bba91 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3353,15 +3353,19 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
{
struct vc_data *vc = vc_cons[fg_console].d;
unsigned char c;
- static DEFINE_SPINLOCK(printing_lock);
+ static atomic_t printing_lock = ATOMIC_INIT(0);
const ushort *start;
ushort start_x, cnt;
int kmsg_console;
WARN_CONSOLE_UNLOCKED();
- /* this protects against concurrent oops only */
- if (!spin_trylock(&printing_lock))
+ /*
+ * Prevent concurrent printing in console_flush_on_panic() where
+ * console_lock is ignored. Easier (serial) console drivers
+ * have bigger chance to get the messages out.
+ */
+ if (atomic_cmpxchg_acquire(&printing_lock, 0, 1) != 0)
return;
kmsg_console = vt_get_kmsg_redirect();
@@ -3422,7 +3426,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
notify_update(vc);
quit:
- spin_unlock(&printing_lock);
+ atomic_set_release(&printing_lock, 0);
}
static struct tty_driver *vt_console_device(struct console *c, int *index)
--
2.52.0
Best Regards,
Petr