diff mbox

[3.19.y-ckt,stable] Patch "can: gs_usb: fixed disconnect bug by removing erroneous use of kfree()" has been added to the 3.19.y-ckt tree

Message ID 1458157280-6303-1-git-send-email-kamal@canonical.com
State New
Headers show

Commit Message

Kamal Mostafa March 16, 2016, 7:41 p.m. UTC
This is a note to let you know that I have just added a patch titled

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

to the linux-3.19.y-queue branch of the 3.19.y-ckt extended stable tree 
which can be found at:

    http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-3.19.y-queue

This patch is scheduled to be released in version 3.19.8-ckt17.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.19.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

---8<------------------------------------------------------------

From bc75938ac3d256d409f78c070011e8cfc21f0fb4 Mon Sep 17 00:00:00 2001
From: Maximilain Schneider <max@schneidersoft.net>
Date: Tue, 23 Feb 2016 01:17:28 +0000
Subject: can: gs_usb: fixed disconnect bug by removing erroneous use of
 kfree()

commit e9a2d81b1761093386a0bb8a4f51642ac785ef63 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: Maximilian Schneider <max@schneidersoft.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
---
 drivers/net/can/usb/gs_usb.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

--
2.7.0
diff mbox

Patch

diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 009acc8..09c23a5 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -826,9 +826,8 @@  static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface
 static void gs_destroy_candev(struct gs_can *dev)
 {
 	unregister_candev(dev->netdev);
-	free_candev(dev->netdev);
 	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)
@@ -911,12 +910,15 @@  static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *
 	for (i = 0; i < icount; i++) {
 		dev->canch[i] = gs_make_candev(i, intf);
 		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 */
 			icount = i;
-			for (i = 0; i < icount; i++) {
+			for (i = 0; i < icount; i++)
 				gs_destroy_candev(dev->canch[i]);
-				dev->canch[i] = NULL;
-			}
+
+			usb_kill_anchored_urbs(&dev->rx_submitted);
 			kfree(dev);
 			return rc;
 		}
@@ -937,16 +939,12 @@  static void gs_usb_disconnect(struct usb_interface *intf)
 		return;
 	}

-	for (i = 0; i < GS_MAX_INTF; i++) {
-		struct gs_can *can = dev->canch[i];
-
-		if (!can)
-			continue;
-
-		gs_destroy_candev(can);
-	}
+	for (i = 0; i < GS_MAX_INTF; i++)
+		if (dev->canch[i])
+			gs_destroy_candev(dev->canch[i]);

 	usb_kill_anchored_urbs(&dev->rx_submitted);
+	kfree(dev);
 }

 static const struct usb_device_id gs_usb_table[] = {