ChangeSet 1.1143.1.5, 2003/03/19 15:41:23-08:00, green@linuxhacker.ru

[PATCH] USB: Memleak in drivers/usb/hub.c::usb_reset_device

Hello!

On Fri, Mar 14, 2003 at 11:37:19AM -0800, Greg KH wrote:
> >    There seems to be a memleak in drivers/usb/hub.c::usb_reset_device()
> >    on error exit path. See the patch.
> >    Found with help of smatch + enhanced unfree script.
> And yes, as David said, there is another kind of error in this area for
> 2.5.  Patches to clean that up would be appreciated.

Ok, I guess something like that should work:


 drivers/usb/core/hub.c |   27 ++++++++++++++++++---------
 1 files changed, 18 insertions(+), 9 deletions(-)


diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Thu Mar 20 15:03:51 2003
+++ b/drivers/usb/core/hub.c	Thu Mar 20 15:03:51 2003
@@ -1175,7 +1175,7 @@
 int usb_reset_device(struct usb_device *dev)
 {
 	struct usb_device *parent = dev->parent;
-	struct usb_device_descriptor descriptor;
+	struct usb_device_descriptor *descriptor;
 	int i, ret, port = -1;
 
 	if (!parent) {
@@ -1224,17 +1224,24 @@
 	 * If nothing changed, we reprogram the configuration and then
 	 * the alternate settings.
 	 */
-	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor,
-			sizeof(descriptor));
-	if (ret < 0)
+	descriptor = kmalloc(sizeof *descriptor, GFP_NOIO);
+	if (!descriptor) {
+		return -ENOMEM;
+	}
+	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor,
+			sizeof(*descriptor));
+	if (ret < 0) {
+		kfree(descriptor);
 		return ret;
+	}
 
-	le16_to_cpus(&descriptor.bcdUSB);
-	le16_to_cpus(&descriptor.idVendor);
-	le16_to_cpus(&descriptor.idProduct);
-	le16_to_cpus(&descriptor.bcdDevice);
+	le16_to_cpus(&descriptor->bcdUSB);
+	le16_to_cpus(&descriptor->idVendor);
+	le16_to_cpus(&descriptor->idProduct);
+	le16_to_cpus(&descriptor->bcdDevice);
 
-	if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) {
+	if (memcmp(&dev->descriptor, descriptor, sizeof(*descriptor))) {
+		kfree(descriptor);
 		usb_destroy_configuration(dev);
 
 		ret = usb_get_device_descriptor(dev);
@@ -1267,6 +1274,8 @@
 
 		return 1;
 	}
+
+	kfree(descriptor);
 
 	ret = usb_set_configuration(dev, dev->actconfig->desc.bConfigurationValue);
 	if (ret < 0) {
