[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <00d001dbe72a$62281bc0$26785340$@samsung.com>
Date: Fri, 27 Jun 2025 15:11:55 +0900
From: "Peter GJ. Park" <gyujoon.park@...sung.com>
To: "'Paolo Abeni'" <pabeni@...hat.com>, "'Oliver Neukum'"
<oneukum@...e.com>, "'Andrew Lunn'" <andrew+netdev@...n.ch>, "'David S.
Miller'" <davem@...emloft.net>, "'Eric Dumazet'" <edumazet@...gle.com>,
"'Jakub Kicinski'" <kuba@...nel.org>
Cc: <netdev@...r.kernel.org>, <linux-usb@...r.kernel.org>,
<linux-kernel@...r.kernel.org>
Subject: RE: [PATCH net] net: usb: usbnet: fix use-after-free in race on
workqueue
>On 6/25/25 11:33 AM, Peter GJ. Park wrote:
>> When usbnet_disconnect() queued while usbnet_probe() processing, it
>> results to free_netdev before kevent gets to run on workqueue, thus
>> workqueue does assign_work() with referencing freeed memory address.
>>
>> For graceful disconnect and to prevent use-after-free of netdev
>> pointer, the fix adds canceling work and timer those are placed by
>> usbnet_probe()
>>
>> Signed-off-by: Peter GJ. Park <gyujoon.park@...sung.com>
>
>You should include a suitable fixes tag, and you should have specified the target tree ('net' in this case) in the prefix subjext
Prefix net added to subject, but for fixes tag, by looking git blame, the last line of usbnet_disconnect()are based on initial commit,
thus I couldn't put the fixes tag for it. Please let me know how can I handle this.
>
>> ---
>> drivers/net/usb/usbnet.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index
>> c04e715a4c2ade3bc5587b0df71643a25cf88c55..3c5d9ba7fa6660273137c8010674
>> 6103f84f5a37 100644
>> --- a/drivers/net/usb/usbnet.c
>> +++ b/drivers/net/usb/usbnet.c
>> @@ -1660,6 +1660,9 @@ void usbnet_disconnect (struct usb_interface *intf)
>> usb_free_urb(dev->interrupt);
>> kfree(dev->padding_pkt);
>>
>> + timer_delete_sync(&dev->delay);
>> + tasklet_kill(&dev->bh);
>> + cancel_work_sync(&dev->kevent);
>> free_netdev(net);
>
>This happens after unregister_netdev(), which calls usbnet_stop() that already performs the above cleanup. How the race is supposed to take place?
>
This uaf detected while my syzkaller project for usb kernel driver.
First hub_event work:usb_new_device arrived and processing in wq,
While second new hub_event work:usb_disconnect put into wq.
Then third usbnet:kevent work put by first hub_event work.
Dev pointer free-ed by second work without preceding usbnet_stop(), so the usbnetkevent still queued in wq,
Finally it detected by kasan as use-after-free when wq try to access that poiter.
Here is log snippet.
[ 3041.949116] [5: kworker/5:1: 130] BUG: KASAN: slab-use-after-free in assign_work+0xe8/0x280
[ 3041.949128] [5: kworker/5:1: 130] Read of size 8 at addr ffffff88ef60ece8 by task kworker/5:1/130
...
[ 3041.949155] [5: kworker/5:1: 130] Workqueue: 0x0 (usb_hub_wq)
[ 3041.949167] [5: kworker/5:1: 130] Call trace:
[ 3041.949170] [5: kworker/5:1: 130] dump_backtrace+0x120/0x170
[ 3041.949178] [5: kworker/5:1: 130] show_stack+0x2c/0x40
[ 3041.949184] [5: kworker/5:1: 130] dump_stack_lvl+0x68/0x84
[ 3041.949193] [5: kworker/5:1: 130] print_report+0x13c/0x6f8
[ 3041.949203] [5: kworker/5:1: 130] kasan_report+0xdc/0x13c
[ 3041.949211] [5: kworker/5:1: 130] __asan_load8+0x98/0xa0
[ 3041.949216] [5: kworker/5:1: 130] assign_work+0xe8/0x280
[ 3041.949224] [5: kworker/5:1: 130] worker_thread+0x458/0x670
[ 3041.949231] [5: kworker/5:1: 130] kthread+0x1d8/0x298
[ 3041.949238] [5: kworker/5:1: 130] ret_from_fork+0x10/0x20
[ 3041.949248] [5: kworker/5:1: 130] Allocated by task 130:
...
[ 3041.949275] [5: kworker/5:1: 130] __kmalloc_node+0x74/0x194
[ 3041.949282] [5: kworker/5:1: 130] kvmalloc_node+0x160/0x394
[ 3041.949289] [5: kworker/5:1: 130] alloc_netdev_mqs+0x6c/0x718
[ 3041.949298] [5: kworker/5:1: 130] alloc_etherdev_mqs+0x48/0x60
[ 3041.949305] [5: kworker/5:1: 130] usbnet_probe+0xd8/0xf10 [usbnet]
[ 3041.949348] [5: kworker/5:1: 130] usb_probe_interface+0x338/0x4fc
...
[ 3041.949516] [5: kworker/5:1: 130] usb_new_device+0x7c8/0xbdc
[ 3041.949523] [5: kworker/5:1: 130] hub_event+0x1808/0x2564
[ 3041.949530] [5: kworker/5:1: 130] process_scheduled_works+0x3cc/0x92c
[ 3041.949538] [5: kworker/5:1: 130] worker_thread+0x468/0x670
[ 3041.949546] [5: kworker/5:1: 130] kthread+0x1d8/0x298
[ 3041.949552] [5: kworker/5:1: 130] ret_from_fork+0x10/0x20
[ 3041.949561] [5: kworker/5:1: 130] Freed by task 130:
...
[ 3041.949604] [5: kworker/5:1: 130] __kmem_cache_free+0xa0/0x260
[ 3041.949610] [5: kworker/5:1: 130] kfree+0x60/0x124
[ 3041.949617] [5: kworker/5:1: 130] kvfree+0x40/0x54
[ 3041.949622] [5: kworker/5:1: 130] netdev_freemem+0x2c/0x40
[ 3041.949630] [5: kworker/5:1: 130] netdev_release+0x50/0x6c
[ 3041.949638] [5: kworker/5:1: 130] device_release+0x74/0x13c
[ 3041.949645] [5: kworker/5:1: 130] kobject_put+0xfc/0x1a8
[ 3041.949654] [5: kworker/5:1: 130] put_device+0x28/0x40
[ 3041.949660] [5: kworker/5:1: 130] free_netdev+0x234/0x284
[ 3041.949667] [5: kworker/5:1: 130] usbnet_disconnect+0x18c/0x250 [usbnet]
[ 3041.949706] [5: kworker/5:1: 130] usb_unbind_interface+0x130/0x414
[ 3041.949713] [5: kworker/5:1: 130] device_release_driver_internal+0x2e8/0x494
[ 3041.949721] [5: kworker/5:1: 130] device_release_driver+0x28/0x3c
[ 3041.949730] [5: kworker/5:1: 130] bus_remove_device+0x250/0x268
[ 3041.949737] [5: kworker/5:1: 130] device_del+0x304/0x530
[ 3041.949744] [5: kworker/5:1: 130] usb_disable_device+0x1d8/0x340
[ 3041.949750] [5: kworker/5:1: 130] usb_disconnect+0x1c4/0x4f0
[ 3041.949757] [5: kworker/5:1: 130] hub_event+0x1200/0x2564
[ 3041.949764] [5: kworker/5:1: 130] process_scheduled_works+0x3cc/0x92c
[ 3041.949772] [5: kworker/5:1: 130] worker_thread+0x468/0x670
[ 3041.949780] [5: kworker/5:1: 130] kthread+0x1d8/0x298
[ 3041.949786] [5: kworker/5:1: 130] ret_from_fork+0x10/0x20
[ 3041.949796] [5: kworker/5:1: 130] Last potentially related work creation:
...
[ 3041.949820] [5: kworker/5:1: 130] __queue_work+0x5d0/0xaf4
[ 3041.949827] [5: kworker/5:1: 130] queue_work_on+0x64/0xb0
[ 3041.949833] [5: kworker/5:1: 130] usbnet_link_change+0xdc/0x13c [usbnet]
[ 3041.949873] [5: kworker/5:1: 130] usbnet_probe+0xe5c/0xf10 [usbnet]
...
[ 3041.950078] [5: kworker/5:1: 130] usb_new_device+0x7c8/0xbdc
[ 3041.950085] [5: kworker/5:1: 130] hub_event+0x1808/0x2564
[ 3041.950092] [5: kworker/5:1: 130] process_scheduled_works+0x3cc/0x92c
[ 3041.950100] [5: kworker/5:1: 130] worker_thread+0x468/0x670
[ 3041.950107] [5: kworker/5:1: 130] kthread+0x1d8/0x298
[ 3041.950113] [5: kworker/5:1: 130] ret_from_fork+0x10/0x20
[ 3041.950120] [5: kworker/5:1: 130]
>/P
Powered by blists - more mailing lists