[PATCH 1/3] vt: order the fg_console switch against vt_console_print()

From: Jaidev Shastri via B4 Relay

Date: Mon Sep 21 2026 - 21:31:34 EST


From: Jaidev Shastri <jaidevshastri@xxxxxx>

redraw_screen() switches fg_console with a plain store once the new
console's state is set up. vt_console_print(), the printk console
callback, indexes vc_cons[] with fg_console before it takes
printing_lock.

Store the new index with smp_store_release() and read it with
smp_load_acquire(), so that the printk path cannot reach the slot before
the console it denotes is complete.

Found with MBCheck, a static herd7-based memory consistency checker.

Signed-off-by: Jaidev Shastri <jaidevshastri@xxxxxx>
---
drivers/tty/vt/vt.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 57edf3749..3abbd6cf9 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -973,7 +973,8 @@ void redraw_screen(struct vc_data *vc, int is_switch)
if (!con_is_visible(vc))
redraw = 1;
*vc->vc_display_fg = vc;
- fg_console = vc->vc_num;
+ /* Pairs with the smp_load_acquire() in vt_console_print(). */
+ smp_store_release(&fg_console, vc->vc_num);
hide_cursor(old_vc);
if (!con_is_visible(old_vc)) {
save_screen(old_vc);
@@ -3447,7 +3448,8 @@ int vt_kmsg_redirect(int new)

static void vt_console_print(struct console *co, const char *b, unsigned count)
{
- struct vc_data *vc = vc_cons[fg_console].d;
+ /* Pairs with the smp_store_release() in redraw_screen(). */
+ struct vc_data *vc = vc_cons[smp_load_acquire(&fg_console)].d;
unsigned char c;
static DEFINE_SPINLOCK(printing_lock);
const ushort *start;

--
2.43.0