usb/core: slab-out-of-bounds in usb_get_bos_descriptor
From: Andrey Konovalov
Date: Wed Oct 18 2017 - 08:10:36 EST
Hi!
I've got the following report while fuzzing the kernel with syzkaller.
On commit 3e0cc09a3a2c40ec1ffb6b4e12da86e98feccb11 (4.14-rc5+).
Looks like usb_get_bos_descriptor() doesn't check that buffer has
enough space for usb_dev_cap_header, which causes out-of-bounds
accesses.
==================================================================
BUG: KASAN: slab-out-of-bounds in usb_get_bos_descriptor+0x621/0x670
Read of size 1 at addr ffff88006b21625a by task kworker/0:2/1254
CPU: 0 PID: 1254 Comm: kworker/0:2 Not tainted
4.14.0-rc5-43687-g49c387c9bdf6 #468
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
Call Trace:
__dump_stack lib/dump_stack.c:16
dump_stack+0x292/0x395 lib/dump_stack.c:52
print_address_description+0x78/0x280 mm/kasan/report.c:252
kasan_report_error mm/kasan/report.c:351
kasan_report+0x23d/0x350 mm/kasan/report.c:409
__asan_report_load1_noabort+0x19/0x20 mm/kasan/report.c:427
usb_get_bos_descriptor+0x621/0x670 drivers/usb/core/config.c:963
hub_port_init+0x18e5/0x2860 drivers/usb/core/hub.c:4642
hub_port_connect drivers/usb/core/hub.c:4835
hub_port_connect_change drivers/usb/core/hub.c:5009
port_event drivers/usb/core/hub.c:5115
hub_event+0x17b3/0x3740 drivers/usb/core/hub.c:5195
process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
worker_thread+0x221/0x1850 kernel/workqueue.c:2253
kthread+0x363/0x440 kernel/kthread.c:231
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
Allocated by task 1254:
save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
save_stack+0x43/0xd0 mm/kasan/kasan.c:447
set_track mm/kasan/kasan.c:459
kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551
__kmalloc+0x14e/0x310 mm/slub.c:3782
kmalloc ./include/linux/slab.h:498
kzalloc ./include/linux/slab.h:666
usb_get_bos_descriptor+0x1cb/0x670 drivers/usb/core/config.c:944
hub_port_init+0x18e5/0x2860 drivers/usb/core/hub.c:4642
hub_port_connect drivers/usb/core/hub.c:4835
hub_port_connect_change drivers/usb/core/hub.c:5009
port_event drivers/usb/core/hub.c:5115
hub_event+0x17b3/0x3740 drivers/usb/core/hub.c:5195
process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
worker_thread+0x221/0x1850 kernel/workqueue.c:2253
kthread+0x363/0x440 kernel/kthread.c:231
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
Freed by task 2853:
save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
save_stack+0x43/0xd0 mm/kasan/kasan.c:447
set_track mm/kasan/kasan.c:459
kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524
slab_free_hook mm/slub.c:1390
slab_free_freelist_hook mm/slub.c:1412
slab_free mm/slub.c:2988
kfree+0xf6/0x2f0 mm/slub.c:3919
load_elf_binary+0x39af/0x4f90 fs/binfmt_elf.c:1087
search_binary_handler+0x146/0x480 fs/exec.c:1634
exec_binprm fs/exec.c:1676
do_execveat_common.isra.31+0x16d2/0x2200 fs/exec.c:1798
do_execve fs/exec.c:1842
SYSC_execve fs/exec.c:1923
SyS_execve+0x3e/0x50 fs/exec.c:1918
do_syscall_64+0x2c5/0x850 arch/x86/entry/common.c:287
return_from_SYSCALL_64+0x0/0x7a arch/x86/entry/entry_64.S:245
The buggy address belongs to the object at ffff88006b216240
which belongs to the cache kmalloc-32 of size 32
The buggy address is located 26 bytes inside of
32-byte region [ffff88006b216240, ffff88006b216260)
The buggy address belongs to the page:
page:ffffea0001ac8580 count:1 mapcount:0 mapping: (null) index:0x0
flags: 0x100000000000100(slab)
raw: 0100000000000100 0000000000000000 0000000000000000 0000000180550055
raw: ffffea0001b16640 0000000b0000000b ffff88006c403980 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88006b216100: fb fb fc fc fb fb fb fb fc fc 00 00 00 00 fc fc
ffff88006b216180: fb fb fb fb fc fc fb fb fb fb fc fc fb fb fb fb
>ffff88006b216200: fc fc fb fb fb fb fc fc 00 00 00 02 fc fc fb fb
^
ffff88006b216280: fb fb fc fc fb fb fb fb fc fc fb fb fb fb fc fc
ffff88006b216300: fb fb fb fb fc fc fb fb fb fb fc fc fb fb fb fb
==================================================================