[alsa-devel] UAF write in usb_audio_probe
Mathias Payer
mathias.payer at nebelwelt.net
Mon Dec 3 14:40:19 CET 2018
Hi there,
We are submitting a patch for an UAF write in usb_audio_probe. A malicious USB
device can send a broken device configuration that will trigger a free of the
underlying object before it is decremented. I'm sending the patch and KASAN
report after discussing with Takashi on the security mailing list so that he can
merge.
The attacker needs local access to plug in a malicious USB device that replays
the trace (e.g., through FaceDancer) to get read/write primitives in the kernel.
For, e.g., Android or locked Desktops this becomes security critical.
This bug is present in 4.14.81 through to HEAD (i.e., all versions we tested).
The place where UAF is triggered is in `usb_audio_probe` in `sound/usb/card.c`.
In the error handling code in `usb_audio_probe`, if the number of interfaces
read from the device side is zero, `chip->card` object is freed. Unfortunately,
the `chip` object is part of the `card` object, thus, when `chip->card` is
freed, `chip` is also freed.
However, in the error handling code, the `active` field will be written to
by an `atomic_dec` operation, resulting in an UAF write.
```
static int usb_audio_probe(struct usb_interface *intf,
const struct usb_device_id *usb_id)
.....
__error:
if (chip) {
if (!chip->num_interfaces)
snd_card_free(chip->card);
// UAF write
atomic_dec(&chip->active);
}
mutex_unlock(®ister_mutex);
return err;
```
The attacker can race the snd_card_free and the atomic_dec by attaching new USB
devices (the attacker can time when what parts of the first malicious device are
read then play with attaching the second device; the race is arbitrarily
repeatable). The new USB device descriptors will use the recently freed memory
which is then modified by the atomic_dec, resulting in an attacker-controlled
decrement operation to, e.g., a USB data structure under the attacker's control.
We have also attached the KASAN report from when the bug was triggered.
The patch for card.c is attached. It moves the atomic_dec to above the free of
the chip memory object, ensuring that, if no cards are left, the decrement
happens before the free. We've also added a comment to clarify that the two
objects are dependent.
Thanks,
Hui Peng
Mathias Payer
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bug1.patch
Type: text/x-patch
Size: 1380 bytes
Desc: not available
URL: <http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20181203/3763ba52/attachment-0001.bin>
-------------- next part --------------
BUG: KASAN: use-after-free in atomic_dec include/asm-generic/atomic-instrumented.h:114 [inline]
BUG: KASAN: use-after-free in usb_audio_probe+0xee7/0x2220 sound/usb/card.c:687
Write of size 4 at addr ffff88012f91d114 by task test/5641
CPU: 2 PID: 5641 Comm: test Not tainted 4.18.19 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0xf2/0x188 lib/dump_stack.c:113
print_address_description+0x71/0x239 mm/kasan/report.c:256
kasan_report_error mm/kasan/report.c:354 [inline]
kasan_report.cold.6+0x242/0x2fe mm/kasan/report.c:412
check_memory_region_inline mm/kasan/kasan.c:260 [inline]
check_memory_region+0x13e/0x1b0 mm/kasan/kasan.c:267
kasan_check_write+0x14/0x20 mm/kasan/kasan.c:278
atomic_dec include/asm-generic/atomic-instrumented.h:114 [inline]
usb_audio_probe+0xee7/0x2220 sound/usb/card.c:687
usb_probe_interface+0x324/0x940 drivers/usb/core/driver.c:361
really_probe drivers/base/dd.c:438 [inline]
driver_probe_device+0x598/0x7f0 drivers/base/dd.c:580
__device_attach_driver+0x25f/0x2e0 drivers/base/dd.c:676
bus_for_each_drv+0x124/0x190 drivers/base/bus.c:461
__device_attach+0x1ca/0x2d0 drivers/base/dd.c:733
device_initial_probe+0x1f/0x30 drivers/base/dd.c:780
bus_probe_device+0x200/0x2b0 drivers/base/bus.c:521
device_add+0x8b5/0x1460 drivers/base/core.c:1875
usb_set_configuration+0xd5f/0x1780 drivers/usb/core/message.c:2014
generic_probe+0xbb/0x120 drivers/usb/core/generic.c:174
usb_probe_device+0xb4/0x110 drivers/usb/core/driver.c:266
really_probe drivers/base/dd.c:438 [inline]
driver_probe_device+0x598/0x7f0 drivers/base/dd.c:580
__device_attach_driver+0x25f/0x2e0 drivers/base/dd.c:676
bus_for_each_drv+0x124/0x190 drivers/base/bus.c:461
__device_attach+0x1ca/0x2d0 drivers/base/dd.c:733
device_initial_probe+0x1f/0x30 drivers/base/dd.c:780
bus_probe_device+0x200/0x2b0 drivers/base/bus.c:521
device_add+0x8b5/0x1460 drivers/base/core.c:1875
usb_new_device+0x9f9/0x1f30 drivers/usb/core/hub.c:2563
hub_port_connect drivers/usb/core/hub.c:5067 [inline]
hub_port_connect_change drivers/usb/core/hub.c:5182 [inline]
port_event drivers/usb/core/hub.c:5290 [inline]
hub_event_impl+0x189b/0x3670 drivers/usb/core/hub.c:5402
uf_hub_events_handle+0x504/0x53e drivers/usb/core/hub.c:1874
hub_ioctl+0x4fb/0x550 drivers/usb/core/hub.c:1924
proc_ioctl+0x3e1/0x610 drivers/usb/core/devio.c:2187
proc_ioctl_default drivers/usb/core/devio.c:2210 [inline]
usbdev_do_ioctl+0x61a/0x2e20 drivers/usb/core/devio.c:2524
usbdev_ioctl+0x2a/0x40 drivers/usb/core/devio.c:2568
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:500 [inline]
do_vfs_ioctl+0x16d/0x1160 fs/ioctl.c:684
ksys_ioctl+0xae/0xd0 fs/ioctl.c:701
__do_sys_ioctl fs/ioctl.c:708 [inline]
__se_sys_ioctl fs/ioctl.c:706 [inline]
__x64_sys_ioctl+0x78/0xb0 fs/ioctl.c:706
do_syscall_64+0xd4/0x4e0 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x452d07
Code: 48 83 c4 08 48 89 d8 5b 5d c3 66 0f 1f 84 00 00 00 00 00 48 89 e8 48 f7 d8 48 39 c3 0f 92 c0 eb 92 66 90 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 0f 83 7d bb fb ff c3 66 66 66 2e 0f 1f 84 00 00
RSP: 002b:00007fff9dea3de8 EFLAGS: 00000206 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000452d07
RDX: 00007fff9dea3e00 RSI: 00000000c0105512 RDI: 0000000000000000
RBP: 0000000020004ff2 R08: 0000000020000a74 R09: 0000000020001000
R10: 0000000000000004 R11: 0000000000000206 R12: 0000000000000074
R13: 0000000020000a74 R14: 0000000000000004 R15: 0000000000000003
Allocated by task 5641:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
kasan_kmalloc+0xc7/0xe0 mm/kasan/kasan.c:553
__kmalloc+0x161/0x330 mm/slub.c:3753
kmalloc include/linux/slab.h:518 [inline]
kzalloc include/linux/slab.h:707 [inline]
snd_card_new+0x92/0x8b0 sound/core/init.c:214
snd_usb_audio_create sound/usb/card.c:475 [inline]
usb_audio_probe+0x12da/0x2220 sound/usb/card.c:621
usb_probe_interface+0x324/0x940 drivers/usb/core/driver.c:361
really_probe drivers/base/dd.c:438 [inline]
driver_probe_device+0x598/0x7f0 drivers/base/dd.c:580
__device_attach_driver+0x25f/0x2e0 drivers/base/dd.c:676
bus_for_each_drv+0x124/0x190 drivers/base/bus.c:461
__device_attach+0x1ca/0x2d0 drivers/base/dd.c:733
device_initial_probe+0x1f/0x30 drivers/base/dd.c:780
bus_probe_device+0x200/0x2b0 drivers/base/bus.c:521
device_add+0x8b5/0x1460 drivers/base/core.c:1875
usb_set_configuration+0xd5f/0x1780 drivers/usb/core/message.c:2014
generic_probe+0xbb/0x120 drivers/usb/core/generic.c:174
usb_probe_device+0xb4/0x110 drivers/usb/core/driver.c:266
really_probe drivers/base/dd.c:438 [inline]
driver_probe_device+0x598/0x7f0 drivers/base/dd.c:580
__device_attach_driver+0x25f/0x2e0 drivers/base/dd.c:676
bus_for_each_drv+0x124/0x190 drivers/base/bus.c:461
__device_attach+0x1ca/0x2d0 drivers/base/dd.c:733
device_initial_probe+0x1f/0x30 drivers/base/dd.c:780
bus_probe_device+0x200/0x2b0 drivers/base/bus.c:521
device_add+0x8b5/0x1460 drivers/base/core.c:1875
usb_new_device+0x9f9/0x1f30 drivers/usb/core/hub.c:2563
hub_port_connect drivers/usb/core/hub.c:5067 [inline]
hub_port_connect_change drivers/usb/core/hub.c:5182 [inline]
port_event drivers/usb/core/hub.c:5290 [inline]
hub_event_impl+0x189b/0x3670 drivers/usb/core/hub.c:5402
uf_hub_events_handle+0x504/0x53e drivers/usb/core/hub.c:1874
hub_ioctl+0x4fb/0x550 drivers/usb/core/hub.c:1924
proc_ioctl+0x3e1/0x610 drivers/usb/core/devio.c:2187
proc_ioctl_default drivers/usb/core/devio.c:2210 [inline]
usbdev_do_ioctl+0x61a/0x2e20 drivers/usb/core/devio.c:2524
usbdev_ioctl+0x2a/0x40 drivers/usb/core/devio.c:2568
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:500 [inline]
do_vfs_ioctl+0x16d/0x1160 fs/ioctl.c:684
ksys_ioctl+0xae/0xd0 fs/ioctl.c:701
__do_sys_ioctl fs/ioctl.c:708 [inline]
__se_sys_ioctl fs/ioctl.c:706 [inline]
__x64_sys_ioctl+0x78/0xb0 fs/ioctl.c:706
do_syscall_64+0xd4/0x4e0 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Freed by task 5641:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
__kasan_slab_free+0x139/0x190 mm/kasan/kasan.c:521
kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
slab_free_hook mm/slub.c:1373 [inline]
slab_free_freelist_hook mm/slub.c:1400 [inline]
slab_free mm/slub.c:2955 [inline]
kfree+0x107/0x310 mm/slub.c:3908
snd_card_do_free sound/core/init.c:501 [inline]
release_card_device+0x116/0x180 sound/core/init.c:181
device_release+0x83/0x210 drivers/base/core.c:850
kobject_cleanup lib/kobject.c:643 [inline]
kobject_release lib/kobject.c:672 [inline]
kref_put include/linux/kref.h:70 [inline]
kobject_put+0x198/0x290 lib/kobject.c:689
put_device+0x25/0x30 drivers/base/core.c:1972
snd_card_free_when_closed sound/core/init.c:519 [inline]
snd_card_free+0x9a/0xd0 sound/core/init.c:544
usb_audio_probe+0x108f/0x2220 sound/usb/card.c:686
usb_probe_interface+0x324/0x940 drivers/usb/core/driver.c:361
really_probe drivers/base/dd.c:438 [inline]
driver_probe_device+0x598/0x7f0 drivers/base/dd.c:580
__device_attach_driver+0x25f/0x2e0 drivers/base/dd.c:676
bus_for_each_drv+0x124/0x190 drivers/base/bus.c:461
__device_attach+0x1ca/0x2d0 drivers/base/dd.c:733
device_initial_probe+0x1f/0x30 drivers/base/dd.c:780
bus_probe_device+0x200/0x2b0 drivers/base/bus.c:521
device_add+0x8b5/0x1460 drivers/base/core.c:1875
usb_set_configuration+0xd5f/0x1780 drivers/usb/core/message.c:2014
generic_probe+0xbb/0x120 drivers/usb/core/generic.c:174
usb_probe_device+0xb4/0x110 drivers/usb/core/driver.c:266
really_probe drivers/base/dd.c:438 [inline]
driver_probe_device+0x598/0x7f0 drivers/base/dd.c:580
__device_attach_driver+0x25f/0x2e0 drivers/base/dd.c:676
bus_for_each_drv+0x124/0x190 drivers/base/bus.c:461
__device_attach+0x1ca/0x2d0 drivers/base/dd.c:733
device_initial_probe+0x1f/0x30 drivers/base/dd.c:780
bus_probe_device+0x200/0x2b0 drivers/base/bus.c:521
device_add+0x8b5/0x1460 drivers/base/core.c:1875
usb_new_device+0x9f9/0x1f30 drivers/usb/core/hub.c:2563
hub_port_connect drivers/usb/core/hub.c:5067 [inline]
hub_port_connect_change drivers/usb/core/hub.c:5182 [inline]
port_event drivers/usb/core/hub.c:5290 [inline]
hub_event_impl+0x189b/0x3670 drivers/usb/core/hub.c:5402
uf_hub_events_handle+0x504/0x53e drivers/usb/core/hub.c:1874
hub_ioctl+0x4fb/0x550 drivers/usb/core/hub.c:1924
proc_ioctl+0x3e1/0x610 drivers/usb/core/devio.c:2187
proc_ioctl_default drivers/usb/core/devio.c:2210 [inline]
usbdev_do_ioctl+0x61a/0x2e20 drivers/usb/core/devio.c:2524
usbdev_ioctl+0x2a/0x40 drivers/usb/core/devio.c:2568
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:500 [inline]
do_vfs_ioctl+0x16d/0x1160 fs/ioctl.c:684
ksys_ioctl+0xae/0xd0 fs/ioctl.c:701
__do_sys_ioctl fs/ioctl.c:708 [inline]
__se_sys_ioctl fs/ioctl.c:706 [inline]
__x64_sys_ioctl+0x78/0xb0 fs/ioctl.c:706
do_syscall_64+0xd4/0x4e0 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff88012f91c400
which belongs to the cache kmalloc-4096 of size 4096
The buggy address is located 3348 bytes inside of
4096-byte region [ffff88012f91c400, ffff88012f91d400)
The buggy address belongs to the page:
page:ffffea0004be4600 count:1 mapcount:0 mapping:ffff880064802c00 index:0x0 compound_mapcount: 0
flags: 0x600000000008100(slab|head)
raw: 0600000000008100 0000000000000000 0000000100000001 ffff880064802c00
raw: 0000000000000000 0000000080070007 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88012f91d000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88012f91d080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff88012f91d100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff88012f91d180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88012f91d200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20181203/3763ba52/attachment-0001.sig>
More information about the Alsa-devel
mailing list