lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ