Commit 27d7c245 authored by Maximilain Schneider's avatar Maximilain Schneider Committed by Luis Henriques

can: gs_usb: fixed disconnect bug by removing erroneous use of kfree()

commit e9a2d81b upstream.

gs_destroy_candev() erroneously calls kfree() on a struct gs_can *, which is
allocated through alloc_candev() and should instead be freed using
free_candev() alone.

The inappropriate use of kfree() causes the kernel to hang when
gs_destroy_candev() is called.

Only the struct gs_usb * which is allocated through kzalloc() should be freed
using kfree() when the device is disconnected.
Signed-off-by: default avatarMaximilian Schneider <max@schneidersoft.net>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent a59cc348
...@@ -825,9 +825,8 @@ static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface ...@@ -825,9 +825,8 @@ static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface
static void gs_destroy_candev(struct gs_can *dev) static void gs_destroy_candev(struct gs_can *dev)
{ {
unregister_candev(dev->netdev); unregister_candev(dev->netdev);
free_candev(dev->netdev);
usb_kill_anchored_urbs(&dev->tx_submitted); usb_kill_anchored_urbs(&dev->tx_submitted);
kfree(dev); free_candev(dev->netdev);
} }
static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
...@@ -910,12 +909,15 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id * ...@@ -910,12 +909,15 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *
for (i = 0; i < icount; i++) { for (i = 0; i < icount; i++) {
dev->canch[i] = gs_make_candev(i, intf); dev->canch[i] = gs_make_candev(i, intf);
if (IS_ERR_OR_NULL(dev->canch[i])) { if (IS_ERR_OR_NULL(dev->canch[i])) {
/* save error code to return later */
rc = PTR_ERR(dev->canch[i]);
/* on failure destroy previously created candevs */ /* on failure destroy previously created candevs */
icount = i; icount = i;
for (i = 0; i < icount; i++) { for (i = 0; i < icount; i++)
gs_destroy_candev(dev->canch[i]); gs_destroy_candev(dev->canch[i]);
dev->canch[i] = NULL;
} usb_kill_anchored_urbs(&dev->rx_submitted);
kfree(dev); kfree(dev);
return rc; return rc;
} }
...@@ -936,16 +938,12 @@ static void gs_usb_disconnect(struct usb_interface *intf) ...@@ -936,16 +938,12 @@ static void gs_usb_disconnect(struct usb_interface *intf)
return; return;
} }
for (i = 0; i < GS_MAX_INTF; i++) { for (i = 0; i < GS_MAX_INTF; i++)
struct gs_can *can = dev->canch[i]; if (dev->canch[i])
gs_destroy_candev(dev->canch[i]);
if (!can)
continue;
gs_destroy_candev(can);
}
usb_kill_anchored_urbs(&dev->rx_submitted); usb_kill_anchored_urbs(&dev->rx_submitted);
kfree(dev);
} }
static const struct usb_device_id gs_usb_table[] = { static const struct usb_device_id gs_usb_table[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment