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: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250701041900.ruz5a6ymeyc3hgxf@U20PB1-1082.tn.corp.samsungelectronics.net>
Date: Tue, 1 Jul 2025 13:19:00 +0900
From: "Peter GJ. Park" <gyujoon.park@...sung.com>
To: Paolo Abeni <pabeni@...hat.com>
Cc: 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>, 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 Thu, Jun 26, 2025 at 11:21:39AM +0200, Paolo Abeni wrote:
> 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
>
It has been applied with v2 patch. Thank you for 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..3c5d9ba7fa6660273137c80106746103f84f5a37 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?
>
> /P
>
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

Best Regards,
GJ


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ