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
commit 37685fb0b2d13d676038f8602569d1e5faa29ef5 Author: Mathias Payer <mathias.payer@xxxxxxxxxxxxx> Date: Mon Dec 3 05:09:54 2018 +0100 ALSA: usb-audio: Fix UAF decrement if card has no live interfaces in card.c From: Hui Peng <benquike@xxxxxxxxx> If a USB sound card reports 0 interfaces, an error condition is triggered and the function usb_audio_probe errors out. In the error path, there was a use-after-free vulnerability where the memory object of the card was first freed, followed by a decrement of the number of active chips. Moving the decrement above the atomic_dec fixes the UAF. Reported-by: Hui Peng <benquike@xxxxxxxxx> Reported-by: Mathias Payer <mathias.payer@xxxxxxxxxxxxx> Signed-off-by: Hui Peng <benquike@xxxxxxxxx> Signed-off-by: Mathias Payer <mathias.payer@xxxxxxxxxxxxx> diff --git a/sound/usb/card.c b/sound/usb/card.c index 2bfe4e80a6b9..3ea9c125731c 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -682,9 +682,12 @@ static int usb_audio_probe(struct usb_interface *intf, __error: if (chip) { + /* chip->active is inside the chip->card object, + * decrement before memory is possibly returned. + */ + atomic_dec(&chip->active); if (!chip->num_interfaces) snd_card_free(chip->card); - atomic_dec(&chip->active); } mutex_unlock(®ister_mutex); return err;
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 ==================================================================
Attachment:
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel