usb/core: slab-out-of-bounds in usb_set_configuration

321 views
Skip to first unread message

Andrey Konovalov

unread,
Sep 18, 2017, 1:22:25 PM9/18/17
to Greg Kroah-Hartman, Jaejoong Kim, Jonathan Corbet, Mauro Carvalho Chehab, USB list, LKML, syzkaller, Kostya Serebryany, Dmitry Vyukov
Hi!

I've got the following crash while fuzzing the kernel with syzkaller.

On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).

It seems there's no proper size check of a
USB_DT_INTERFACE_ASSOCIATION descriptor. It's only checked that the
size is >= 2 in usb_parse_configuration(), so find_iad() might do
out-of-bounds access to intf_assoc->bInterfaceCount.

gadgetfs: bound to dummy_udc driver
usb 1-1: new full-speed USB device number 2 using dummy_hcd
gadgetfs: connected
gadgetfs: disconnected
gadgetfs: connected
usb 1-1: config 1 interface 0 altsetting 0 has an invalid endpoint
with address 0x0, skipping
usb 1-1: New USB device found, idVendor=0020, idProduct=410e
usb 1-1: New USB device strings: Mfr=0, Product=8, SerialNumber=3
usb 1-1: Product: a
usb 1-1: SerialNumber: a
==================================================================
BUG: KASAN: slab-out-of-bounds in usb_set_configuration+0x1859/0x1870
Read of size 1 at addr ffff88006a9d00de by task kworker/0:2/1260

CPU: 0 PID: 1260 Comm: kworker/0:2 Not tainted
4.14.0-rc1-42251-gebb2c2437d80 #169
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+0x22f/0x340 mm/kasan/report.c:409
__asan_report_load1_noabort+0x19/0x20 mm/kasan/report.c:427
find_iad drivers/usb/core/message.c:1644
usb_set_configuration+0x1859/0x1870 drivers/usb/core/message.c:1855
generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
really_probe drivers/base/dd.c:413
driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
__device_attach_driver+0x230/0x290 drivers/base/dd.c:653
bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
__device_attach+0x26e/0x3d0 drivers/base/dd.c:710
device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
device_add+0xd0b/0x1660 drivers/base/core.c:1835
usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
hub_port_connect drivers/usb/core/hub.c:4903
hub_port_connect_change drivers/usb/core/hub.c:5009
port_event drivers/usb/core/hub.c:5115
hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
worker_thread+0x221/0x1850 kernel/workqueue.c:2253
kthread+0x3a1/0x470 kernel/kthread.c:231
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Allocated by task 1260:
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
usb_get_configuration+0x372/0x2a60 drivers/usb/core/config.c:848
usb_enumerate_device drivers/usb/core/hub.c:2290
usb_new_device+0xaae/0x1020 drivers/usb/core/hub.c:2426
hub_port_connect drivers/usb/core/hub.c:4903
hub_port_connect_change drivers/usb/core/hub.c:5009
port_event drivers/usb/core/hub.c:5115
hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
worker_thread+0x221/0x1850 kernel/workqueue.c:2253
kthread+0x3a1/0x470 kernel/kthread.c:231
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Freed by task 2870:
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+0x39c2/0x4fa0 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/0x830 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 ffff88006a9d00c0
which belongs to the cache kmalloc-32 of size 32
The buggy address is located 30 bytes inside of
32-byte region [ffff88006a9d00c0, ffff88006a9d00e0)
The buggy address belongs to the page:
page:ffffea0001aa7400 count:1 mapcount:0 mapping: (null)
index:0xffff88006a9d05a0
flags: 0x100000000000100(slab)
raw: 0100000000000100 0000000000000000 ffff88006a9d05a0 0000000180550054
raw: ffffea000193fa00 0000001400000014 ffff88006c403980 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
ffff88006a9cff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88006a9d0000: fb fb fb fb fc fc fb fb fb fb fc fc fb fb fb fb
>ffff88006a9d0080: fc fc fb fb fb fb fc fc 00 00 00 05 fc fc fb fb
^
ffff88006a9d0100: fb fb fc fc fb fb fb fb fc fc fb fb fb fb fc fc
ffff88006a9d0180: 00 00 00 00 fc fc 00 00 00 00 fc fc fb fb fb fb
==================================================================

Greg Kroah-Hartman

unread,
Sep 18, 2017, 2:50:30 PM9/18/17
to Andrey Konovalov, Jaejoong Kim, Jonathan Corbet, Mauro Carvalho Chehab, USB list, LKML, syzkaller, Kostya Serebryany, Dmitry Vyukov
On Mon, Sep 18, 2017 at 07:22:24PM +0200, Andrey Konovalov wrote:
> Hi!
>
> I've got the following crash while fuzzing the kernel with syzkaller.
>
> On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).
>
> It seems there's no proper size check of a
> USB_DT_INTERFACE_ASSOCIATION descriptor. It's only checked that the
> size is >= 2 in usb_parse_configuration(), so find_iad() might do
> out-of-bounds access to intf_assoc->bInterfaceCount.

Ah, nice catch!

Does the patch below fix this?

thanks,

greg k-h

---------------

diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 4be52c602e9b..a3dbac1938ec 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -643,15 +643,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,

} else if (header->bDescriptorType ==
USB_DT_INTERFACE_ASSOCIATION) {
+ struct usb_interface_assoc_descriptor *d;
+
+ d = (struct usb_interface_assoc_descriptor *)header;
+ if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) {
+ dev_warn(ddev,
+ "config %d has an invalid interface association descriptor of length %d, skipping\n",
+ cfgno, d->bLength);
+ continue;
+ }
+
if (iad_num == USB_MAXIADS) {
dev_warn(ddev, "found more Interface "
"Association Descriptors "
"than allocated for in "
"configuration %d\n", cfgno);
} else {
- config->intf_assoc[iad_num] =
- (struct usb_interface_assoc_descriptor
- *)header;
+ config->intf_assoc[iad_num] = d;
iad_num++;
}

diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
index ce1169af39d7..2a5d63040a0b 100644
--- a/include/uapi/linux/usb/ch9.h
+++ b/include/uapi/linux/usb/ch9.h
@@ -780,6 +780,7 @@ struct usb_interface_assoc_descriptor {
__u8 iFunction;
} __attribute__ ((packed));

+#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8

/*-------------------------------------------------------------------------*/

Andrey Konovalov

unread,
Sep 19, 2017, 7:54:58 AM9/19/17
to Greg Kroah-Hartman, Jaejoong Kim, Jonathan Corbet, Mauro Carvalho Chehab, USB list, LKML, syzkaller, Kostya Serebryany, Dmitry Vyukov
On Mon, Sep 18, 2017 at 8:50 PM, Greg Kroah-Hartman
<gre...@linuxfoundation.org> wrote:
> On Mon, Sep 18, 2017 at 07:22:24PM +0200, Andrey Konovalov wrote:
>> Hi!
>>
>> I've got the following crash while fuzzing the kernel with syzkaller.
>>
>> On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).
>>
>> It seems there's no proper size check of a
>> USB_DT_INTERFACE_ASSOCIATION descriptor. It's only checked that the
>> size is >= 2 in usb_parse_configuration(), so find_iad() might do
>> out-of-bounds access to intf_assoc->bInterfaceCount.
>
> Ah, nice catch!
>
> Does the patch below fix this?

Hi Greg,

I believe it does and the bug is no longer triggered with the
reproducer that I have.

Tested-by: Andrey Konovalov <andre...@google.com>

Thanks!
> --
> You received this message because you are subscribed to the Google Groups "syzkaller" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to syzkaller+...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Greg Kroah-Hartman

unread,
Sep 19, 2017, 8:39:50 AM9/19/17
to Andrey Konovalov, Jaejoong Kim, Jonathan Corbet, Mauro Carvalho Chehab, USB list, LKML, syzkaller, Kostya Serebryany, Dmitry Vyukov
On Tue, Sep 19, 2017 at 01:54:57PM +0200, Andrey Konovalov wrote:
> On Mon, Sep 18, 2017 at 8:50 PM, Greg Kroah-Hartman
> <gre...@linuxfoundation.org> wrote:
> > On Mon, Sep 18, 2017 at 07:22:24PM +0200, Andrey Konovalov wrote:
> >> Hi!
> >>
> >> I've got the following crash while fuzzing the kernel with syzkaller.
> >>
> >> On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).
> >>
> >> It seems there's no proper size check of a
> >> USB_DT_INTERFACE_ASSOCIATION descriptor. It's only checked that the
> >> size is >= 2 in usb_parse_configuration(), so find_iad() might do
> >> out-of-bounds access to intf_assoc->bInterfaceCount.
> >
> > Ah, nice catch!
> >
> > Does the patch below fix this?
>
> Hi Greg,
>
> I believe it does and the bug is no longer triggered with the
> reproducer that I have.
>
> Tested-by: Andrey Konovalov <andre...@google.com>

Thanks for testing, I'll go queue this up.

greg k-h
Reply all
Reply to author
Forward
0 new messages