Skip to contentSkip to conversation

qcserial: fix a memory leak in qcprobe error path

PATCH Superseded Axel Lin 2 participants 3 messages Jun 8, 2010 – Jun 16, 2010

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Axel Lin

author
#0 lore raw

PATCH 1/1 qcserial: fix a memory leak in qcprobe error path

In current implemtation, the "data" is not kfreed in qcprobe error path. This patch moves the memory allocation a little bit latter and only allocate memory when no error is detected in previous checking.

---
 drivers/usb/serial/qcserial.c |   30 +++++++++++++++++-------------
 1 files changed, 17 insertions(+), 13 deletions(-)
drivers/usb/serial/qcserial.c +17 -13
index 04bb759..d30078c 100644
@@ -109,13 +109,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 	ifnum = intf->desc.bInterfaceNumber;
 	dbg("This Interface = %d", ifnum);
 
-	data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
-					 GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	spin_lock_init(&data->susp_lock);
-
 	switch (nintf) {
 	case 1:
 		/* QDL mode */
@@ -130,8 +123,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 		    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
 			dbg("QDL port found");
 
-			if (serial->interface->num_altsetting == 1)
-				return 0;
+			if (serial->interface->num_altsetting == 1) {
+				retval = 0;
+				goto out;
+			}
 
 			retval = usb_set_interface(serial->dev, ifnum, 1);
 			if (retval < 0) {
@@ -140,7 +135,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 					retval);
 				retval = -ENODEV;
 			}
-			return retval;
+			goto out;
 		}
 		break;
 
@@ -156,17 +151,26 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 					retval);
 				retval = -ENODEV;
 			}
-			return retval;
+			goto out;
 		}
 		break;
 
 	default:
 		dev_err(&serial->dev->dev,
 			"unknown number of interfaces: %d\n", nintf);
-		return -ENODEV;
 	}
 
-	return retval;
+out:
+	if (retval)
+		return retval;
+
+	data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
+					 GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spin_lock_init(&data->susp_lock);
+	return 0;
 }
 
 static struct usb_serial_driver qcdevice = {
Signature · 1 line
1.5.4.3
#1 lore raw
Quoted 3 lines · Axel Lin

In current implemtation, the "data" is not kfreed in qcprobe error path. This patch moves the memory allocation a little bit latter and only allocate memory when no error is detected in previous checking.

Yeah, but it's now pretty messy.

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 118

Quoted 13 lines
drivers/usb/serial/qcserial.c +0 -7
@@ -109,13 +109,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 	ifnum = intf->desc.bInterfaceNumber;
 	dbg("This Interface = %d", ifnum);
 
-	data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
-					 GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	spin_lock_init(&data->susp_lock);
-

Moving this to the end is fine.

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 138

Quoted 6 lines
drivers/usb/serial/qcserial.c +1 -1
@@ -140,7 +135,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 					retval);
 				retval = -ENODEV;
 			}
-			return retval;
+			goto out;

But this doesn't need to be changed, right?
Or this.

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 154

Quoted 9 lines
drivers/usb/serial/qcserial.c +1 -1
 		}
 		break;
 
@@ -156,17 +151,26 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 					retval);
 				retval = -ENODEV;
 			}
-			return retval;
+			goto out;

Or this?

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 166

Quoted 7 lines
drivers/usb/serial/qcserial.c +0 -1
 		}
 		break;
 
 	default:
 		dev_err(&serial->dev->dev,
 			"unknown number of interfaces: %d\n", nintf);
-		return -ENODEV;

Hm. maybe.

Quoted 4 lines
drivers/usb/serial/qcserial.c +1 -1
 	}
 
-	return retval;
+out:

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 173

Quoted 10 lines
drivers/usb/serial/qcserial.c +10 -0
+	if (retval)
+		return retval;
+
+	data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
+					 GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spin_lock_init(&data->susp_lock);
+	return 0;

I guess it's ok, I just don't like doing data initialization on the "out" path, it's messy.

Care to neaten this up a bit more and resend it? Perhaps just free the memory on the error path instead of moving it later on?

thanks,

greg k-h

author
#2 lore raw

hi Greg,

2010/6/15 Greg KH <[email protected]>:

Quoted 73 lines · Axel Lin
Quoted 3 lines

In current implemtation, the "data" is not kfreed in qcprobe error path. This patch moves the memory allocation a little bit latter and only allocate memory when no error is detected in previous checking.

Yeah, but it's now pretty messy.

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 118

Quoted 13 lines
drivers/usb/serial/qcserial.c +0 -7
@@ -109,13 +109,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
       ifnum = intf->desc.bInterfaceNumber;
       dbg("This Interface = %d", ifnum);
 
-     data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
-                                      GFP_KERNEL);
-     if (!data)
-             return -ENOMEM;
-
-     spin_lock_init(&data->susp_lock);
-

Moving this to the end is fine.

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 138

Quoted 6 lines
drivers/usb/serial/qcserial.c +1 -1
@@ -140,7 +135,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                       retval);
                               retval = -ENODEV;
                       }
-                     return retval;
+                     goto out;

But this doesn't need to be changed, right?
Or this.

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 154

Quoted 9 lines
drivers/usb/serial/qcserial.c +1 -1
               }
               break;
 
@@ -156,17 +151,26 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                       retval);
                               retval = -ENODEV;
                       }
-                     return retval;
+                     goto out;

Or this?

Quoted 7 lines
drivers/usb/serial/qcserial.c +0 -0
               }
               break;
 

      default:
              dev_err(&serial->dev->dev,
                      "unknown number of interfaces: %d\n", nintf);
-             return -ENODEV;

Hm. maybe.

Quoted 4 lines

      }

-     return retval;

drivers/usb/serial/qcserial.c +1 -0
+out:

drivers/usb/serial/qcserial.c static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) · line 173

Quoted 10 lines
drivers/usb/serial/qcserial.c +10 -0
+     if (retval)
+             return retval;
+
+     data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
+                                      GFP_KERNEL);
+     if (!data)
+             return -ENOMEM;
+
+     spin_lock_init(&data->susp_lock);
+     return 0;

I guess it's ok, I just don't like doing data initialization on the "out" path, it's messy.

Quoted 2 lines

Care to neaten this up a bit more and resend it?  Perhaps just free the memory on the error path instead of moving it later on?

I will send a revised patch that just free the memory on the error path. Thanks for the review.

Axel

Quoted 5 lines

thanks,

greg k-h