[PATCH 5/6] vt: keyboard: recompute the shift state into locals before publishing it
From: Jaidev Shastri via B4 Relay
Date: Mon Sep 21 2026 - 21:30:15 EST
From: Jaidev Shastri <jaidevshastri@xxxxxx>
do_compute_shiftstate() clears shift_state and shift_down[] and rebuilds
them in place while it iterates key_down[]. vt_get_shift_state() reads
shift_state without kbd_event_lock and can observe the cleared or
partially rebuilt value.
Compute the new state into locals, copy shift_down[] first and publish
shift_state last with smp_store_release().
Found with MBCheck, a static herd7-based memory consistency checker.
Signed-off-by: Jaidev Shastri <jaidevshastri@xxxxxx>
---
drivers/tty/vt/keyboard.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index c2fd92e2b..87970415a 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -403,10 +403,9 @@ static void set_leds(void)
static void do_compute_shiftstate(void)
{
+ unsigned char down[NR_SHIFT] = { 0 };
unsigned int k, sym, val;
-
- shift_state = 0;
- memset(shift_down, 0, sizeof(shift_down));
+ int state = 0;
for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
sym = U(key_maps[0][k]);
@@ -417,9 +416,17 @@ static void do_compute_shiftstate(void)
if (val == KVAL(K_CAPSSHIFT))
val = KVAL(K_SHIFT);
- shift_down[val]++;
- shift_state |= BIT(val);
+ down[val]++;
+ state |= BIT(val);
}
+
+ memcpy(shift_down, down, sizeof(shift_down));
+ /*
+ * Publish the recomputed state in one step. vt_get_shift_state()
+ * reads shift_state without kbd_event_lock; pairs with its
+ * smp_load_acquire().
+ */
+ smp_store_release(&shift_state, state);
}
/* We still have to export this method to vt.c */
--
2.43.0