Message ID | 20220923042551.2745-1-yepeilin.cs@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | a43206156263fbaf1f2b7f96257441f331e91bb7 |
Headers | show |
Series | [net] usbnet: Fix memory leak in usbnet_disconnect() | expand |
On 23.09.22 06:25, Peilin Ye wrote: Hi, > I think we may have similar issues at other usb_scuttle_anchored_urbs() > call sites. Since urb->context is (void *), should we pass a "destructor" > callback to usb_scuttle_anchored_urbs(), or replace this function with > usb_get_from_anchor() loops like this patch does? > please introduce a new function with an additional parameter for that, so that we do not need to touch the correct usages. Regards Oliver
Hello: This patch was applied to netdev/net.git (master) by Jakub Kicinski <kuba@kernel.org>: On Thu, 22 Sep 2022 21:25:51 -0700 you wrote: > From: Peilin Ye <peilin.ye@bytedance.com> > > Currently usbnet_disconnect() unanchors and frees all deferred URBs > using usb_scuttle_anchored_urbs(), which does not free urb->context, > causing a memory leak as reported by syzbot. > > Use a usb_get_from_anchor() while loop instead, similar to what we did > in commit 19cfe912c37b ("Bluetooth: btusb: Fix memory leak in > play_deferred"). Also free urb->sg. > > [...] Here is the summary with links: - [net] usbnet: Fix memory leak in usbnet_disconnect() https://git.kernel.org/netdev/net/c/a43206156263 You are awesome, thank you!
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index fd399a8ed973..64a9a80b2309 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1598,6 +1598,7 @@ void usbnet_disconnect (struct usb_interface *intf) struct usbnet *dev; struct usb_device *xdev; struct net_device *net; + struct urb *urb; dev = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); @@ -1614,7 +1615,11 @@ void usbnet_disconnect (struct usb_interface *intf) net = dev->net; unregister_netdev (net); - usb_scuttle_anchored_urbs(&dev->deferred); + while ((urb = usb_get_from_anchor(&dev->deferred))) { + dev_kfree_skb(urb->context); + kfree(urb->sg); + usb_free_urb(urb); + } if (dev->driver_info->unbind) dev->driver_info->unbind(dev, intf);