diff mbox series

ZDI-CAN-22166: New Vulnerability Report

Message ID DM5PR0102MB3477C75A38D67E275032FADB80C0A@DM5PR0102MB3477.prod.exchangelabs.com (mailing list archive)
State RFC
Headers show
Series ZDI-CAN-22166: New Vulnerability Report | expand

Checks

Context Check Description
netdev/tree_selection success Guessing tree name failed - patch did not apply

Commit Message

zdi-disclosures@trendmicro.com Sept. 29, 2023, 7 p.m. UTC
The attachment could not be scanned for viruses because it is a password protected file.
ZDI-CAN-22166: Linux Kernel usbnet Driver Race Condition Privilege Escalation Vulnerability

-- CVSS -----------------------------------------

7.1: AV:P/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H

-- ABSTRACT -------------------------------------

Trend Micro's Zero Day Initiative has identified a vulnerability affecting the following products:
Linux - Kernel

-- VULNERABILITY DETAILS ------------------------
* Version tested:6.6-rc1
* Installer file:-
* Platform tested:debian bullseye

---

### Analysis

```
race condition bug exist in usbnet driver
usbnet_disconnect() didn't flush/cancel the usbnet_deferred_kevent work queue before disconnecting
it can then trigger the UAF on struct net_device by racing bewteen usbnet_disconnect() and usbnet_deferred_kevent()
```


i patched the kernel to trigger it easily
```
```

~~~C++
static void
usbnet_deferred_kevent (struct work_struct *work)
{
        struct usbnet           *dev =
                container_of(work, struct usbnet, kevent);
        int                     status;

        /* usb_clear_halt() needs a thread context */
        if (test_bit (EVENT_TX_HALT, &dev->flags)) {                    // access on the freed dev
                unlink_urbs (dev, &dev->txq);
                status = usb_autopm_get_interface(dev->intf);
                if (status < 0)
                        goto fail_pipe;
                status = usb_clear_halt (dev->udev, dev->out);
                usb_autopm_put_interface(dev->intf);
                if (status < 0 &&
                    status != -EPIPE &&
                    status != -ESHUTDOWN) {
                        if (netif_msg_tx_err (dev))
fail_pipe:
                                netdev_err(dev->net, "can't clear tx halt, status %d\n",
                                           status);
                } else {
                        clear_bit (EVENT_TX_HALT, &dev->flags);
                        if (status != -ESHUTDOWN)
                                netif_wake_queue (dev->net);
                }
        }
        if (test_bit (EVENT_RX_HALT, &dev->flags)) {
...
}

~~~


KASAN report
```
==================================================================
BUG: KASAN: slab-use-after-free in instrument_atomic_read /root/linux/./include/linux/instrumented.h:68
BUG: KASAN: slab-use-after-free in _test_bit /root/linux/./include/asm-generic/bitops/instrumented-non-atomic.h:141
BUG: KASAN: slab-use-after-free in usbnet_deferred_kevent+0x35/0xde0 /root/linux/drivers/net/usb/usbnet.c:1141
Read of size 8 at addr ffff8880213291a8 by task kworker/0:2/917

CPU: 0 PID: 917 Comm: kworker/0:2 Not tainted 6.6.0-rc1-dirty #2
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-5 04/01/2014
Workqueue: events usbnet_deferred_kevent
Call Trace:
 <TASK>
 __dump_stack /root/linux/lib/dump_stack.c:88
 dump_stack_lvl+0xd9/0x1b0 /root/linux/lib/dump_stack.c:106
 print_address_description /root/linux/mm/kasan/report.c:364
 print_report+0xc4/0x620 /root/linux/mm/kasan/report.c:475
 kasan_report+0xda/0x110 /root/linux/mm/kasan/report.c:588
 check_region_inline /root/linux/mm/kasan/generic.c:181
 kasan_check_range+0xef/0x190 /root/linux/mm/kasan/generic.c:187
 instrument_atomic_read /root/linux/./include/linux/instrumented.h:68
 _test_bit /root/linux/./include/asm-generic/bitops/instrumented-non-atomic.h:141
 usbnet_deferred_kevent+0x35/0xde0 /root/linux/drivers/net/usb/usbnet.c:1141
 process_one_work+0x887/0x15d0 /root/linux/kernel/workqueue.c:2630
 process_scheduled_works /root/linux/kernel/workqueue.c:2703
 worker_thread+0x8bb/0x1290 /root/linux/kernel/workqueue.c:2784
 kthread+0x33a/0x430 /root/linux/kernel/kthread.c:388
 ret_from_fork+0x45/0x80 /root/linux/arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x11/0x20 /root/linux/arch/x86/entry/entry_64.S:304
 </TASK>

Allocated by task 4496:
 kasan_save_stack+0x33/0x50 /root/linux/mm/kasan/common.c:45
 kasan_set_track+0x25/0x30 /root/linux/mm/kasan/common.c:52
 ____kasan_kmalloc /root/linux/mm/kasan/common.c:374
 __kasan_kmalloc+0xa3/0xb0 /root/linux/mm/kasan/common.c:383
 kasan_kmalloc /root/linux/./include/linux/kasan.h:198
 __do_kmalloc_node /root/linux/mm/slab_common.c:1023
 __kmalloc_node+0x63/0x110 /root/linux/mm/slab_common.c:1030
 kmalloc_node /root/linux/./include/linux/slab.h:619
 kvmalloc_node+0x6f/0x1a0 /root/linux/mm/util.c:607
 kvmalloc /root/linux/./include/linux/slab.h:737
 kvzalloc /root/linux/./include/linux/slab.h:745
 alloc_netdev_mqs+0x9b/0x1290 /root/linux/net/core/dev.c:10681
 usbnet_probe+0x1bc/0x2850 /root/linux/drivers/net/usb/usbnet.c:1698
 usb_probe_interface+0x307/0x930 /root/linux/drivers/usb/core/driver.c:396
 call_driver_probe /root/linux/drivers/base/dd.c:579
 really_probe+0x234/0xc90 /root/linux/drivers/base/dd.c:658
 __driver_probe_device+0x1de/0x4b0 /root/linux/drivers/base/dd.c:800
 driver_probe_device+0x4c/0x1a0 /root/linux/drivers/base/dd.c:830
 __device_attach_driver+0x1d4/0x300 /root/linux/drivers/base/dd.c:958
 bus_for_each_drv+0x157/0x1d0 /root/linux/drivers/base/bus.c:457
 __device_attach+0x1e8/0x4b0 /root/linux/drivers/base/dd.c:1030
 bus_probe_device+0x17c/0x1c0 /root/linux/drivers/base/bus.c:532
 device_add+0x1182/0x1ac0 /root/linux/drivers/base/core.c:3622
 usb_set_configuration+0x10cb/0x1c40 /root/linux/drivers/usb/core/message.c:2207
 usb_generic_driver_probe+0xca/0x130 /root/linux/drivers/usb/core/generic.c:238
 usb_probe_device+0xda/0x2c0 /root/linux/drivers/usb/core/driver.c:293
 call_driver_probe /root/linux/drivers/base/dd.c:579
 really_probe+0x234/0xc90 /root/linux/drivers/base/dd.c:658
 __driver_probe_device+0x1de/0x4b0 /root/linux/drivers/base/dd.c:800
 driver_probe_device+0x4c/0x1a0 /root/linux/drivers/base/dd.c:830
 __device_attach_driver+0x1d4/0x300 /root/linux/drivers/base/dd.c:958
 bus_for_each_drv+0x157/0x1d0 /root/linux/drivers/base/bus.c:457
 __device_attach+0x1e8/0x4b0 /root/linux/drivers/base/dd.c:1030
 bus_probe_device+0x17c/0x1c0 /root/linux/drivers/base/bus.c:532
 device_add+0x1182/0x1ac0 /root/linux/drivers/base/core.c:3622
 usb_new_device+0xd8c/0x1950 /root/linux/drivers/usb/core/hub.c:2589
 hub_port_connect /root/linux/drivers/usb/core/hub.c:5440
 hub_port_connect_change /root/linux/drivers/usb/core/hub.c:5580
 port_event /root/linux/drivers/usb/core/hub.c:5740
 hub_event+0x2daf/0x4e00 /root/linux/drivers/usb/core/hub.c:5822
 process_one_work+0x887/0x15d0 /root/linux/kernel/workqueue.c:2630
 process_scheduled_works /root/linux/kernel/workqueue.c:2703
 worker_thread+0x8bb/0x1290 /root/linux/kernel/workqueue.c:2784
 kthread+0x33a/0x430 /root/linux/kernel/kthread.c:388
 ret_from_fork+0x45/0x80 /root/linux/arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x11/0x20 /root/linux/arch/x86/entry/entry_64.S:304

Freed by task 4496:
 kasan_save_stack+0x33/0x50 /root/linux/mm/kasan/common.c:45
 kasan_set_track+0x25/0x30 /root/linux/mm/kasan/common.c:52
 kasan_save_free_info+0x28/0x40 /root/linux/mm/kasan/generic.c:522
 ____kasan_slab_free /root/linux/mm/kasan/common.c:236
 ____kasan_slab_free+0x138/0x190 /root/linux/mm/kasan/common.c:200
 kasan_slab_free /root/linux/./include/linux/kasan.h:164
 __cache_free /root/linux/mm/slab.c:3370
 __do_kmem_cache_free /root/linux/mm/slab.c:3557
 __kmem_cache_free+0xcc/0x2d0 /root/linux/mm/slab.c:3564
 kvfree+0x47/0x50 /root/linux/mm/util.c:653
 device_release+0xa1/0x240 /root/linux/drivers/base/core.c:2484
 kobject_cleanup /root/linux/lib/kobject.c:682
 kobject_release /root/linux/lib/kobject.c:716
 kref_put /root/linux/./include/linux/kref.h:65
 kobject_put+0x1d0/0x440 /root/linux/lib/kobject.c:733
 put_device+0x1f/0x30 /root/linux/drivers/base/core.c:3730
 free_netdev+0x408/0x5f0 /root/linux/net/core/dev.c:10831
 usbnet_disconnect+0x26b/0x540 /root/linux/drivers/net/usb/usbnet.c:1637
 usb_unbind_interface+0x1dd/0x8d0 /root/linux/drivers/usb/core/driver.c:458
 device_remove /root/linux/drivers/base/dd.c:569
 device_remove+0x11f/0x170 /root/linux/drivers/base/dd.c:561
 __device_release_driver /root/linux/drivers/base/dd.c:1272
 device_release_driver_internal+0x44a/0x610 /root/linux/drivers/base/dd.c:1295
 bus_remove_device+0x22c/0x420 /root/linux/drivers/base/bus.c:574
 device_del+0x39a/0xa50 /root/linux/drivers/base/core.c:3811
 usb_disable_device+0x36c/0x7f0 /root/linux/drivers/usb/core/message.c:1416
 usb_disconnect+0x2e1/0x890 /root/linux/drivers/usb/core/hub.c:2252
 hub_port_connect /root/linux/drivers/usb/core/hub.c:5280
 hub_port_connect_change /root/linux/drivers/usb/core/hub.c:5580
 port_event /root/linux/drivers/usb/core/hub.c:5740
 hub_event+0x1db7/0x4e00 /root/linux/drivers/usb/core/hub.c:5822
 process_one_work+0x887/0x15d0 /root/linux/kernel/workqueue.c:2630
 process_scheduled_works /root/linux/kernel/workqueue.c:2703
 worker_thread+0x8bb/0x1290 /root/linux/kernel/workqueue.c:2784
 kthread+0x33a/0x430 /root/linux/kernel/kthread.c:388
 ret_from_fork+0x45/0x80 /root/linux/arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x11/0x20 /root/linux/arch/x86/entry/entry_64.S:304

Last potentially related work creation:
 kasan_save_stack+0x33/0x50 /root/linux/mm/kasan/common.c:45
 __kasan_record_aux_stack+0x78/0x80 /root/linux/mm/kasan/generic.c:492
 insert_work+0x38/0x230 /root/linux/kernel/workqueue.c:1647
 __queue_work+0x5d2/0x1060 /root/linux/kernel/workqueue.c:1799
 queue_work_on+0xed/0x110 /root/linux/kernel/workqueue.c:1834
 queue_work /root/linux/./include/linux/workqueue.h:554
 schedule_work /root/linux/./include/linux/workqueue.h:615
 usbnet_defer_kevent+0x7b/0x240 /root/linux/drivers/net/usb/usbnet.c:470
 usbnet_link_change /root/linux/drivers/net/usb/usbnet.c:2000
 usbnet_probe+0x1a4b/0x2850 /root/linux/drivers/net/usb/usbnet.c:1845
 usb_probe_interface+0x307/0x930 /root/linux/drivers/usb/core/driver.c:396
 call_driver_probe /root/linux/drivers/base/dd.c:579
 really_probe+0x234/0xc90 /root/linux/drivers/base/dd.c:658
 __driver_probe_device+0x1de/0x4b0 /root/linux/drivers/base/dd.c:800
 driver_probe_device+0x4c/0x1a0 /root/linux/drivers/base/dd.c:830
 __device_attach_driver+0x1d4/0x300 /root/linux/drivers/base/dd.c:958
 bus_for_each_drv+0x157/0x1d0 /root/linux/drivers/base/bus.c:457
 __device_attach+0x1e8/0x4b0 /root/linux/drivers/base/dd.c:1030
 bus_probe_device+0x17c/0x1c0 /root/linux/drivers/base/bus.c:532
 device_add+0x1182/0x1ac0 /root/linux/drivers/base/core.c:3622
 usb_set_configuration+0x10cb/0x1c40 /root/linux/drivers/usb/core/message.c:2207
 usb_generic_driver_probe+0xca/0x130 /root/linux/drivers/usb/core/generic.c:238
 usb_probe_device+0xda/0x2c0 /root/linux/drivers/usb/core/driver.c:293
 call_driver_probe /root/linux/drivers/base/dd.c:579
 really_probe+0x234/0xc90 /root/linux/drivers/base/dd.c:658
 __driver_probe_device+0x1de/0x4b0 /root/linux/drivers/base/dd.c:800
 driver_probe_device+0x4c/0x1a0 /root/linux/drivers/base/dd.c:830
 __device_attach_driver+0x1d4/0x300 /root/linux/drivers/base/dd.c:958
 bus_for_each_drv+0x157/0x1d0 /root/linux/drivers/base/bus.c:457
 __device_attach+0x1e8/0x4b0 /root/linux/drivers/base/dd.c:1030
 bus_probe_device+0x17c/0x1c0 /root/linux/drivers/base/bus.c:532
 device_add+0x1182/0x1ac0 /root/linux/drivers/base/core.c:3622
 usb_new_device+0xd8c/0x1950 /root/linux/drivers/usb/core/hub.c:2589
 hub_port_connect /root/linux/drivers/usb/core/hub.c:5440
 hub_port_connect_change /root/linux/drivers/usb/core/hub.c:5580
 port_event /root/linux/drivers/usb/core/hub.c:5740
 hub_event+0x2daf/0x4e00 /root/linux/drivers/usb/core/hub.c:5822
 process_one_work+0x887/0x15d0 /root/linux/kernel/workqueue.c:2630
 process_scheduled_works /root/linux/kernel/workqueue.c:2703
 worker_thread+0x8bb/0x1290 /root/linux/kernel/workqueue.c:2784
 kthread+0x33a/0x430 /root/linux/kernel/kthread.c:388
 ret_from_fork+0x45/0x80 /root/linux/arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x11/0x20 /root/linux/arch/x86/entry/entry_64.S:304

The buggy address belongs to the object at ffff888021328000
 which belongs to the cache kmalloc-cg-8k of size 8192
The buggy address is located 4520 bytes inside of
 freed 8192-byte region [ffff888021328000, ffff88802132a000)

The buggy address belongs to the physical page:
page:ffffea000084ca00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x21328
head:ffffea000084ca00 order:2 entire_mapcount:0 nr_pages_mapped:0 pincount:0
memcg:ffff8880172b3201
flags: 0xfff00000000840(slab|head|node=0|zone=1|lastcpupid=0x7ff)
page_type: 0x1()
raw: 00fff00000000840 ffff888012c4db00 ffffea00006ebd10 ffff888012c4cc50
raw: 0000000000000000 ffff888021328000 0000000100000001 ffff8880172b3201
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 2, migratetype Unmovable, gfp_mask 0x2460c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_RETRY_MAYFAIL|__GFP_COMP|__GFP_THISNODE), pid 4496, tgid 4496 (kworker/0:4), ts 173334243118, free_ts9
 set_page_owner /root/linux/./include/linux/page_owner.h:31
 post_alloc_hook+0x2cf/0x340 /root/linux/mm/page_alloc.c:1536
 prep_new_page /root/linux/mm/page_alloc.c:1543
 get_page_from_freelist+0xee0/0x2f20 /root/linux/mm/page_alloc.c:3170
 __alloc_pages+0x1d0/0x4a0 /root/linux/mm/page_alloc.c:4426
 __alloc_pages_node /root/linux/./include/linux/gfp.h:237
 kmem_getpages /root/linux/mm/slab.c:1356
 cache_grow_begin+0x99/0x3a0 /root/linux/mm/slab.c:2550
 cache_alloc_refill+0x294/0x3a0 /root/linux/mm/slab.c:2923
 ____cache_alloc /root/linux/mm/slab.c:2999
 ____cache_alloc /root/linux/mm/slab.c:2982
 __do_cache_alloc /root/linux/mm/slab.c:3182
 slab_alloc_node /root/linux/mm/slab.c:3230
 __kmem_cache_alloc_node+0x3c9/0x470 /root/linux/mm/slab.c:3521
 __do_kmalloc_node /root/linux/mm/slab_common.c:1022
 __kmalloc_node+0x52/0x110 /root/linux/mm/slab_common.c:1030
 kmalloc_node /root/linux/./include/linux/slab.h:619
 kvmalloc_node+0x6f/0x1a0 /root/linux/mm/util.c:607
 kvmalloc /root/linux/./include/linux/slab.h:737
 kvzalloc /root/linux/./include/linux/slab.h:745
 alloc_netdev_mqs+0x9b/0x1290 /root/linux/net/core/dev.c:10681
 usbnet_probe+0x1bc/0x2850 /root/linux/drivers/net/usb/usbnet.c:1698
 usb_probe_interface+0x307/0x930 /root/linux/drivers/usb/core/driver.c:396
 call_driver_probe /root/linux/drivers/base/dd.c:579
 really_probe+0x234/0xc90 /root/linux/drivers/base/dd.c:658
 __driver_probe_device+0x1de/0x4b0 /root/linux/drivers/base/dd.c:800
 driver_probe_device+0x4c/0x1a0 /root/linux/drivers/base/dd.c:830
 __device_attach_driver+0x1d4/0x300 /root/linux/drivers/base/dd.c:958
 bus_for_each_drv+0x157/0x1d0 /root/linux/drivers/base/bus.c:457
page last free stack trace:
 reset_page_owner /root/linux/./include/linux/page_owner.h:24
 free_pages_prepare /root/linux/mm/page_alloc.c:1136
 free_unref_page_prepare+0x476/0xa40 /root/linux/mm/page_alloc.c:2312
 free_unref_page+0x33/0x3b0 /root/linux/mm/page_alloc.c:2405
 slab_destroy /root/linux/mm/slab.c:1608
 slabs_destroy+0x85/0xc0 /root/linux/mm/slab.c:1628
 drain_array+0x91/0xa0 /root/linux/mm/slab.c:3795
 cache_reap+0x164/0x330 /root/linux/mm/slab.c:3833
 process_one_work+0x887/0x15d0 /root/linux/kernel/workqueue.c:2630
 process_scheduled_works /root/linux/kernel/workqueue.c:2703
 worker_thread+0x8bb/0x1290 /root/linux/kernel/workqueue.c:2784
 kthread+0x33a/0x430 /root/linux/kernel/kthread.c:388
 ret_from_fork+0x45/0x80 /root/linux/arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x11/0x20 /root/linux/arch/x86/entry/entry_64.S:304

Memory state around the buggy address:
 ffff888021329080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff888021329100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff888021329180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                  ^
 ffff888021329200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff888021329280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================
```


-- CREDIT ---------------------------------------
This vulnerability was discovered by:
Lucas Leong (@_wmliang_) of Trend Micro Zero Day Initiative

-- FURTHER DETAILS ------------------------------

Supporting files:


If supporting files were contained with this report they are provided within a password protected ZIP file. The password is the ZDI candidate number in the form: ZDI-CAN-XXXX where XXXX is the ID number.

Please confirm receipt of this report. We expect all vendors to remediate ZDI vulnerabilities within 120 days of the reported date. If you are ready to release a patch at any point leading up to the deadline, please coordinate with us so that we may release our advisory detailing the issue. If the 120-day deadline is reached and no patch has been made available we will release a limited public advisory with our own mitigations, so that the public can protect themselves in the absence of a patch. Please keep us updated regarding the status of this issue and feel free to contact us at any time:

Zero Day Initiative
zdi-disclosures@trendmicro.com

The PGP key used for all ZDI vendor communications is available from:

  http://www.zerodayinitiative.com/documents/disclosures-pgp-key.asc

-- INFORMATION ABOUT THE ZDI --------------------
Established by TippingPoint and acquired by Trend Micro, the Zero Day Initiative (ZDI) neither re-sells vulnerability details nor exploit code. Instead, upon notifying the affected product vendor, the ZDI provides its Trend Micro TippingPoint customers with zero day protection through its intrusion prevention technology. Explicit details regarding the specifics of the vulnerability are not exposed to any parties until an official vendor patch is publicly available.

Please contact us for further details or refer to:

  http://www.zerodayinitiative.com

-- DISCLOSURE POLICY ----------------------------

Our vulnerability disclosure policy is available online at:

  http://www.zerodayinitiative.com/advisories/disclosure_policy/
TREND MICRO EMAIL NOTICE

The information contained in this email and any attachments is confidential and may be subject to copyright or other intellectual property protection. If you are not the intended recipient, you are not authorized to use or disclose this information, and we request that you notify us by reply mail or telephone and delete the original message from your mail system.

For details about what personal information we collect and why, please see our Privacy Notice on our website at: Read privacy policy<http://www.trendmicro.com/privacy>

Comments

Greg Kroah-Hartman Sept. 30, 2023, 6:55 a.m. UTC | #1
On Fri, Sep 29, 2023 at 07:00:54PM +0000, zdi-disclosures@trendmicro.com wrote:
> Trend Micro's Zero Day Initiative has identified a vulnerability affecting the following products:
> Linux - Kernel

As reported to you before, this is NOT a "vulnerability" but rather,
just a normal bug that you are somehow claiming needs to be fixed.

Patches to help resolve the issue would be most appreciated as you are
in the best position to test them.

thanks,

greg k-h
diff mbox series

Patch

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 2d14b0d78..4183e7e07 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -30,7 +30,7 @@ 
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/pm_runtime.h>
-
+#include <linux/delay.h>
 /*-------------------------------------------------------------------------*/

 /*
@@ -1136,7 +1136,7 @@  usbnet_deferred_kevent (struct work_struct *work)
        struct usbnet           *dev =
                container_of(work, struct usbnet, kevent);
        int                     status;
-
+       msleep(100);
        /* usb_clear_halt() needs a thread context */
        if (test_bit (EVENT_TX_HALT, &dev->flags)) {
                unlink_urbs (dev, &dev->txq);