Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 510cccb5 authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

tty/vt/keyboard: fix OOB access in do_compute_shiftstate()



The size of individual keymap in drivers/tty/vt/keyboard.c is NR_KEYS,
which is currently 256, whereas number of keys/buttons in input device (and
therefor in key_down) is much larger - KEY_CNT - 768, and that can cause
out-of-bound access when we do

	sym = U(key_maps[0][k]);

with large 'k'.

To fix it we should not attempt iterating beyond smaller of NR_KEYS and
KEY_CNT.

Also while at it let's switch to for_each_set_bit() instead of open-coding
it.

Reported-by: default avatarSasha Levin <sasha.levin@oracle.com>
Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent e4add7b6
Loading
Loading
Loading
Loading
+9 −21
Original line number Diff line number Diff line
@@ -366,23 +366,12 @@ static void to_utf8(struct vc_data *vc, uint c)

static void do_compute_shiftstate(void)
{
	unsigned int i, j, k, sym, val;
	unsigned int k, sym, val;

	shift_state = 0;
	memset(shift_down, 0, sizeof(shift_down));

	for (i = 0; i < ARRAY_SIZE(key_down); i++) {

		if (!key_down[i])
			continue;

		k = i * BITS_PER_LONG;

		for (j = 0; j < BITS_PER_LONG; j++, k++) {

			if (!test_bit(k, key_down))
				continue;

	for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
		sym = U(key_maps[0][k]);
		if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
			continue;
@@ -392,8 +381,7 @@ static void do_compute_shiftstate(void)
			val = KVAL(K_SHIFT);

		shift_down[val]++;
			shift_state |= (1 << val);
		}
		shift_state |= BIT(val);
	}
}