Skip to content
This repository was archived by the owner on Mar 8, 2025. It is now read-only.

Commit d7e414b

Browse files
dtorMSe1969
authored andcommitted
vt: keyboard: avoid signed integer overflow in k_ascii
When k_ascii is invoked several times in a row there is a potential for signed integer overflow: UBSAN: Undefined behaviour in drivers/tty/vt/keyboard.c:888:19 signed integer overflow: 10 * 1111111111 cannot be represented in type 'int' CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.6.11 chil360#1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: <IRQ> __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xce/0x128 lib/dump_stack.c:118 ubsan_epilogue+0xe/0x30 lib/ubsan.c:154 handle_overflow+0xdc/0xf0 lib/ubsan.c:184 __ubsan_handle_mul_overflow+0x2a/0x40 lib/ubsan.c:205 k_ascii+0xbf/0xd0 drivers/tty/vt/keyboard.c:888 kbd_keycode drivers/tty/vt/keyboard.c:1477 [inline] kbd_event+0x888/0x3be0 drivers/tty/vt/keyboard.c:1495 While it can be worked around by using check_mul_overflow()/ check_add_overflow(), it is better to introduce a separate flag to signal that number pad is being used to compose a symbol, and change type of the accumulator from signed to unsigned, thus avoiding undefined behavior when it overflows. Reported-by: Kyungtae Kim <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]> Cc: stable <[email protected]> Link: https://lore.kernel.org/r/20200525232740.GA262061@dtor-ws Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 65123cb commit d7e414b

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

drivers/tty/vt/keyboard.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ static DEFINE_SPINLOCK(led_lock);
123123
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
124124
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
125125
static bool dead_key_next;
126-
static int npadch = -1; /* -1 or number assembled on pad */
126+
127+
/* Handles a number being assembled on the number pad */
128+
static bool npadch_active;
129+
static unsigned int npadch_value;
130+
127131
static unsigned int diacr;
128132
static char rep; /* flag telling character repeat */
129133

@@ -819,12 +823,12 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
819823
shift_state &= ~(1 << value);
820824

821825
/* kludge */
822-
if (up_flag && shift_state != old_state && npadch != -1) {
826+
if (up_flag && shift_state != old_state && npadch_active) {
823827
if (kbd->kbdmode == VC_UNICODE)
824-
to_utf8(vc, npadch);
828+
to_utf8(vc, npadch_value);
825829
else
826-
put_queue(vc, npadch & 0xff);
827-
npadch = -1;
830+
put_queue(vc, npadch_value & 0xff);
831+
npadch_active = false;
828832
}
829833
}
830834

@@ -842,7 +846,7 @@ static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
842846

843847
static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
844848
{
845-
int base;
849+
unsigned int base;
846850

847851
if (up_flag)
848852
return;
@@ -856,10 +860,12 @@ static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
856860
base = 16;
857861
}
858862

859-
if (npadch == -1)
860-
npadch = value;
861-
else
862-
npadch = npadch * base + value;
863+
if (!npadch_active) {
864+
npadch_value = 0;
865+
npadch_active = true;
866+
}
867+
868+
npadch_value = npadch_value * base + value;
863869
}
864870

865871
static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)

0 commit comments

Comments
 (0)