tty/vt/keyboard: out of bounds access in do_compute_shiftstate
Hi all,
I've hit the following while fuzzing with syzkaller inside a KVM tools guest running the latest -next kernel:
[ 2662.777566] BUG: KASAN: global-out-of-bounds in do_compute_shiftstate+0x161/0x370 at addr ffffffffb2e686a0
[ 2662.777592] Read of size 2 by task syz-executor/30576
[ 2662.777676] Address belongs to variable plain_map+0x200/0x3540
[ 2662.777727] CPU: 2 PID: 30576 Comm: syz-executor Tainted: G B 4.6.0-next-20160527-sasha-00024-g6ab0dc9-dirty #3098
[ 2662.777792] 1ffff1001635bde7 00000000dc4d92d7 ffff8800b1adefc0 ffffffffa3fd0b37
[ 2662.777826] ffffffff00000002 fffffbfff5deeda4 0000000041b58ab3 ffffffffae8dd830
[ 2662.777862] ffffffffa3fd09c8 ffffffffa23fa2e8 ffff8800b1adef98 ffff8801d42a20f8
[ 2662.777868] Call Trace:
[ 2662.777935] dump_stack (lib/dump_stack.c:53) [ 2662.778136] kasan_report_error (include/linux/kasan.h:28 mm/kasan/report.c:211 mm/kasan/report.c:277) [ 2662.778265] __asan_report_load2_noabort (mm/kasan/report.c:317) [ 2662.778318] do_compute_shiftstate (drivers/tty/vt/keyboard.c:386) [ 2662.778332] fn_null (drivers/tty/vt/keyboard.c:625) [ 2662.778345] k_spec (drivers/tty/vt/keyboard.c:645) [ 2662.778361] kbd_event (drivers/tty/vt/keyboard.c:1459 drivers/tty/vt/keyboard.c:1475) [ 2662.778907] input_to_handler (drivers/input/input.c:120 (discriminator 3)) [ 2662.778926] input_pass_values (drivers/input/input.c:148) [ 2662.778944] input_handle_event (drivers/input/input.c:406) [ 2662.779015] input_inject_event (include/linux/rcupdate.h:910 drivers/input/input.c:467) [ 2662.779034] evdev_do_ioctl (drivers/input/evdev.c:1102) [ 2662.779271] evdev_ioctl_handler (drivers/input/evdev.c:1302) [ 2662.779305] evdev_ioctl (drivers/input/evdev.c:1312) [ 2662.779320] do_vfs_ioctl (fs/ioctl.c:44 fs/ioctl.c:674) [ 2662.779463] SyS_ioctl (fs/ioctl.c:689 fs/ioctl.c:680) [ 2662.779511] do_syscall_64 (arch/x86/entry/common.c:350) [ 2662.779530] entry_SYSCALL64_slow_path (arch/x86/entry/entry_64.S:251) [ 2662.779535] Memory state around the buggy address:
[ 2662.779566] ffffffffb2e68580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 2662.779579] ffffffffb2e68600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 2662.779589] >ffffffffb2e68680: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00
[ 2662.779594] ^
[ 2662.779604] ffffffffb2e68700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 2662.779615] ffffffffb2e68780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Thanks,
Sasha
Hi!
(Vojtech added to cc list. This is history.)
Quoted 2 lines
I've hit the following while fuzzing with syzkaller inside a KVM tools guest running the latest -next kernel:
What does syzkaller do? Random syscalls?
Quoted 6 lines
[ 2662.777566] BUG: KASAN: global-out-of-bounds in do_compute_shiftstate+0x161/0x370 at addr ffffffffb2e686a0[ 2662.777592] Read of size 2 by task syz-executor/30576[ 2662.777676] Address belongs to variable plain_map+0x200/0x3540
/*
* Called after returning from RAW mode or when changing consoles - recompute
* shift_down[] and shift_state from key_down[] maybe called when keymap is
* undefined, so that shiftkey release is seen. The caller must hold the
* kbd_event_lock.
*/
static void do_compute_shiftstate(void)
{
unsigned int i, j, 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;
sym = U(key_maps[0][k]);
if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
continue;
val = KVAL(sym);
if (val == KVAL(K_CAPSSHIFT))
val = KVAL(K_SHIFT);
shift_down[val]++;
shift_state |= (1 << val);
}
}
}Best regards,
Pavel
Quoted 45 lines
[ 2662.777727] CPU: 2 PID: 30576 Comm: syz-executor Tainted: G B 4.6.0-next-20160527-sasha-00024-g6ab0dc9-dirty #3098[ 2662.777792] 1ffff1001635bde7 00000000dc4d92d7 ffff8800b1adefc0 ffffffffa3fd0b37[ 2662.777826] ffffffff00000002 fffffbfff5deeda4 0000000041b58ab3 ffffffffae8dd830[ 2662.777862] ffffffffa3fd09c8 ffffffffa23fa2e8 ffff8800b1adef98 ffff8801d42a20f8[ 2662.777868] Call Trace:[ 2662.777935] dump_stack (lib/dump_stack.c:53) [ 2662.778136] kasan_report_error (include/linux/kasan.h:28 mm/kasan/report.c:211 mm/kasan/report.c:277) [ 2662.778265] __asan_report_load2_noabort (mm/kasan/report.c:317) [ 2662.778318] do_compute_shiftstate (drivers/tty/vt/keyboard.c:386) [ 2662.778332] fn_null (drivers/tty/vt/keyboard.c:625) [ 2662.778345] k_spec (drivers/tty/vt/keyboard.c:645) [ 2662.778361] kbd_event (drivers/tty/vt/keyboard.c:1459 drivers/tty/vt/keyboard.c:1475) [ 2662.778907] input_to_handler (drivers/input/input.c:120 (discriminator 3)) [ 2662.778926] input_pass_values (drivers/input/input.c:148) [ 2662.778944] input_handle_event (drivers/input/input.c:406) [ 2662.779015] input_inject_event (include/linux/rcupdate.h:910 drivers/input/input.c:467) [ 2662.779034] evdev_do_ioctl (drivers/input/evdev.c:1102) [ 2662.779271] evdev_ioctl_handler (drivers/input/evdev.c:1302) [ 2662.779305] evdev_ioctl (drivers/input/evdev.c:1312) [ 2662.779320] do_vfs_ioctl (fs/ioctl.c:44 fs/ioctl.c:674) [ 2662.779463] SyS_ioctl (fs/ioctl.c:689 fs/ioctl.c:680) [ 2662.779511] do_syscall_64 (arch/x86/entry/common.c:350) [ 2662.779530] entry_SYSCALL64_slow_path (arch/x86/entry/entry_64.S:251) [ 2662.779535] Memory state around the buggy address:[ 2662.779566] ffffffffb2e68580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779579] ffffffffb2e68600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779589] >ffffffffb2e68680: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00[ 2662.779594] ^[ 2662.779604] ffffffffb2e68700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779615] ffffffffb2e68780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00Thanks,
Sasha
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Greg KH
maintainerQuoted 45 lines · Sasha Levin
Hi all,
I've hit the following while fuzzing with syzkaller inside a KVM tools guest running the latest -next kernel:
[ 2662.777566] BUG: KASAN: global-out-of-bounds in do_compute_shiftstate+0x161/0x370 at addr ffffffffb2e686a0[ 2662.777592] Read of size 2 by task syz-executor/30576[ 2662.777676] Address belongs to variable plain_map+0x200/0x3540[ 2662.777727] CPU: 2 PID: 30576 Comm: syz-executor Tainted: G B 4.6.0-next-20160527-sasha-00024-g6ab0dc9-dirty #3098[ 2662.777792] 1ffff1001635bde7 00000000dc4d92d7 ffff8800b1adefc0 ffffffffa3fd0b37[ 2662.777826] ffffffff00000002 fffffbfff5deeda4 0000000041b58ab3 ffffffffae8dd830[ 2662.777862] ffffffffa3fd09c8 ffffffffa23fa2e8 ffff8800b1adef98 ffff8801d42a20f8[ 2662.777868] Call Trace:[ 2662.777935] dump_stack (lib/dump_stack.c:53) [ 2662.778136] kasan_report_error (include/linux/kasan.h:28 mm/kasan/report.c:211 mm/kasan/report.c:277) [ 2662.778265] __asan_report_load2_noabort (mm/kasan/report.c:317) [ 2662.778318] do_compute_shiftstate (drivers/tty/vt/keyboard.c:386) [ 2662.778332] fn_null (drivers/tty/vt/keyboard.c:625) [ 2662.778345] k_spec (drivers/tty/vt/keyboard.c:645) [ 2662.778361] kbd_event (drivers/tty/vt/keyboard.c:1459 drivers/tty/vt/keyboard.c:1475) [ 2662.778907] input_to_handler (drivers/input/input.c:120 (discriminator 3)) [ 2662.778926] input_pass_values (drivers/input/input.c:148) [ 2662.778944] input_handle_event (drivers/input/input.c:406) [ 2662.779015] input_inject_event (include/linux/rcupdate.h:910 drivers/input/input.c:467) [ 2662.779034] evdev_do_ioctl (drivers/input/evdev.c:1102) [ 2662.779271] evdev_ioctl_handler (drivers/input/evdev.c:1302) [ 2662.779305] evdev_ioctl (drivers/input/evdev.c:1312) [ 2662.779320] do_vfs_ioctl (fs/ioctl.c:44 fs/ioctl.c:674) [ 2662.779463] SyS_ioctl (fs/ioctl.c:689 fs/ioctl.c:680) [ 2662.779511] do_syscall_64 (arch/x86/entry/common.c:350) [ 2662.779530] entry_SYSCALL64_slow_path (arch/x86/entry/entry_64.S:251) [ 2662.779535] Memory state around the buggy address:[ 2662.779566] ffffffffb2e68580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779579] ffffffffb2e68600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Quoted 7 lines
[ 2662.779589] >ffffffffb2e68680: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00[ 2662.779594] ^[ 2662.779604] ffffffffb2e68700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779615] ffffffffb2e68780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Any chance you can get the result of what the fuzzer was trying to send over the ioctl so we could try to track this down?
thanks,
greg k-h
Quoted 45 lines · Sasha Levin
Hi all,
I've hit the following while fuzzing with syzkaller inside a KVM tools guest running the latest -next kernel:
[ 2662.777566] BUG: KASAN: global-out-of-bounds in do_compute_shiftstate+0x161/0x370 at addr ffffffffb2e686a0[ 2662.777592] Read of size 2 by task syz-executor/30576[ 2662.777676] Address belongs to variable plain_map+0x200/0x3540[ 2662.777727] CPU: 2 PID: 30576 Comm: syz-executor Tainted: G B 4.6.0-next-20160527-sasha-00024-g6ab0dc9-dirty #3098[ 2662.777792] 1ffff1001635bde7 00000000dc4d92d7 ffff8800b1adefc0 ffffffffa3fd0b37[ 2662.777826] ffffffff00000002 fffffbfff5deeda4 0000000041b58ab3 ffffffffae8dd830[ 2662.777862] ffffffffa3fd09c8 ffffffffa23fa2e8 ffff8800b1adef98 ffff8801d42a20f8[ 2662.777868] Call Trace:[ 2662.777935] dump_stack (lib/dump_stack.c:53) [ 2662.778136] kasan_report_error (include/linux/kasan.h:28 mm/kasan/report.c:211 mm/kasan/report.c:277) [ 2662.778265] __asan_report_load2_noabort (mm/kasan/report.c:317) [ 2662.778318] do_compute_shiftstate (drivers/tty/vt/keyboard.c:386) [ 2662.778332] fn_null (drivers/tty/vt/keyboard.c:625) [ 2662.778345] k_spec (drivers/tty/vt/keyboard.c:645) [ 2662.778361] kbd_event (drivers/tty/vt/keyboard.c:1459 drivers/tty/vt/keyboard.c:1475) [ 2662.778907] input_to_handler (drivers/input/input.c:120 (discriminator 3)) [ 2662.778926] input_pass_values (drivers/input/input.c:148) [ 2662.778944] input_handle_event (drivers/input/input.c:406) [ 2662.779015] input_inject_event (include/linux/rcupdate.h:910 drivers/input/input.c:467) [ 2662.779034] evdev_do_ioctl (drivers/input/evdev.c:1102) [ 2662.779271] evdev_ioctl_handler (drivers/input/evdev.c:1302) [ 2662.779305] evdev_ioctl (drivers/input/evdev.c:1312) [ 2662.779320] do_vfs_ioctl (fs/ioctl.c:44 fs/ioctl.c:674) [ 2662.779463] SyS_ioctl (fs/ioctl.c:689 fs/ioctl.c:680) [ 2662.779511] do_syscall_64 (arch/x86/entry/common.c:350) [ 2662.779530] entry_SYSCALL64_slow_path (arch/x86/entry/entry_64.S:251) [ 2662.779535] Memory state around the buggy address:[ 2662.779566] ffffffffb2e68580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779579] ffffffffb2e68600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Quoted 7 lines
[ 2662.779589] >ffffffffb2e68680: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00[ 2662.779594] ^[ 2662.779604] ffffffffb2e68700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779615] ffffffffb2e68780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
I think this happens because keymap size in keyboard.c is smaller than keymaps in input devices. Does the patch below fixes this?
Thanks.
Signature · 28 lines
Dmitry tty/vt/keyboard: fix OOB access in do_compute_shiftstate() From: Dmitry Torokhov <[email protected]> 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: Sasha Levin <[email protected]> Cc: [email protected] Signed-off-by: Dmitry Torokhov <[email protected]> --- drivers/tty/vt/keyboard.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-)
drivers/tty/vt/keyboard.c +9 -21
@@ -366,34 +366,22 @@ 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]) +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 ; - k = i *BITS_PER_LONG ; - -for (j =0 ; j <BITS_PER_LONG ; j++, k++) { - -if (!test_bit (k, key_down)) -continue ; + val =KVAL (sym); +if (val ==KVAL (K_CAPSSHIFT )) + val =KVAL (K_SHIFT ); - sym =U (key_maps[0 ][k]); -if (KTYP (sym) !=KT_SHIFT &&KTYP (sym) !=KT_SLOCK ) -continue ; - - val =KVAL (sym); -if (val ==KVAL (K_CAPSSHIFT )) - val =KVAL (K_SHIFT ); - - shift_down[val]++; - shift_state |= (1 << val); - } + shift_down[val]++; + shift_state |=BIT (val); } }
Quoted 48 lines · Dmitry Torokhov
Quoted 47 lines · Sasha Levin
Hi all,
I've hit the following while fuzzing with syzkaller inside a KVM tools guest running the latest -next kernel:
[ 2662.777566] BUG: KASAN: global-out-of-bounds in do_compute_shiftstate+0x161/0x370 at addr ffffffffb2e686a0[ 2662.777592] Read of size 2 by task syz-executor/30576[ 2662.777676] Address belongs to variable plain_map+0x200/0x3540[ 2662.777727] CPU: 2 PID: 30576 Comm: syz-executor Tainted: G B 4.6.0-next-20160527-sasha-00024-g6ab0dc9-dirty #3098[ 2662.777792] 1ffff1001635bde7 00000000dc4d92d7 ffff8800b1adefc0 ffffffffa3fd0b37[ 2662.777826] ffffffff00000002 fffffbfff5deeda4 0000000041b58ab3 ffffffffae8dd830[ 2662.777862] ffffffffa3fd09c8 ffffffffa23fa2e8 ffff8800b1adef98 ffff8801d42a20f8[ 2662.777868] Call Trace:[ 2662.777935] dump_stack (lib/dump_stack.c:53) [ 2662.778136] kasan_report_error (include/linux/kasan.h:28 mm/kasan/report.c:211 mm/kasan/report.c:277) [ 2662.778265] __asan_report_load2_noabort (mm/kasan/report.c:317) [ 2662.778318] do_compute_shiftstate (drivers/tty/vt/keyboard.c:386) [ 2662.778332] fn_null (drivers/tty/vt/keyboard.c:625) [ 2662.778345] k_spec (drivers/tty/vt/keyboard.c:645) [ 2662.778361] kbd_event (drivers/tty/vt/keyboard.c:1459 drivers/tty/vt/keyboard.c:1475) [ 2662.778907] input_to_handler (drivers/input/input.c:120 (discriminator 3)) [ 2662.778926] input_pass_values (drivers/input/input.c:148) [ 2662.778944] input_handle_event (drivers/input/input.c:406) [ 2662.779015] input_inject_event (include/linux/rcupdate.h:910 drivers/input/input.c:467) [ 2662.779034] evdev_do_ioctl (drivers/input/evdev.c:1102) [ 2662.779271] evdev_ioctl_handler (drivers/input/evdev.c:1302) [ 2662.779305] evdev_ioctl (drivers/input/evdev.c:1312) [ 2662.779320] do_vfs_ioctl (fs/ioctl.c:44 fs/ioctl.c:674) [ 2662.779463] SyS_ioctl (fs/ioctl.c:689 fs/ioctl.c:680) [ 2662.779511] do_syscall_64 (arch/x86/entry/common.c:350) [ 2662.779530] entry_SYSCALL64_slow_path (arch/x86/entry/entry_64.S:251) [ 2662.779535] Memory state around the buggy address:[ 2662.779566] ffffffffb2e68580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779579] ffffffffb2e68600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779589] >ffffffffb2e68680: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00
Quoted 8 lines
Quoted 5 lines
[ 2662.779594] ^[ 2662.779604] ffffffffb2e68700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[ 2662.779615] ffffffffb2e68780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00I think this happens because keymap size in
keyboard.cis smaller than keymaps in input devices. Does the patch below fixes this?
Anyone willing to look it over and add reviewed-by/tested-by?
Quoted 81 lines
Thanks.
Signature · 28 lines
Dmitry tty/vt/keyboard: fix OOB access in do_compute_shiftstate() From: Dmitry Torokhov <[email protected]> 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: Sasha Levin <[email protected]> Cc: [email protected] Signed-off-by: Dmitry Torokhov <[email protected]> --- drivers/tty/vt/keyboard.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-)drivers/tty/vt/keyboard.c +9
-21@@ -366,34 +366,22 @@ 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]) +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 ; - k = i *BITS_PER_LONG ; - -for (j =0 ; j <BITS_PER_LONG ; j++, k++) { - -if (!test_bit (k, key_down)) -continue ; + val =KVAL (sym); +if (val ==KVAL (K_CAPSSHIFT )) + val =KVAL (K_SHIFT ); - sym =U (key_maps[0 ][k]); -if (KTYP (sym) !=KT_SHIFT &&KTYP (sym) !=KT_SLOCK ) -continue ; - - val =KVAL (sym); -if (val ==KVAL (K_CAPSSHIFT )) - val =KVAL (K_SHIFT ); - - shift_down[val]++; - shift_state |= (1 << val); - } + shift_down[val]++; + shift_state |=BIT (val); } }
Signature · 1 line
Dmitry