This patch fixes the most blatant problems that can happen when an error
is encountered during descriptor parsing.

        The struct device embedded within a struct usb_interface is
initialized as soon as the structure is allocated, so that when
put_device() is called it will contain valid data.

        put_device() is not called for unallocated interfaces.

        The pointers in config->extra are freed when the struct 
usb_host_config is freed.

        rawdescriptor pointers are initialized to 0 so that they can be 
freed without error.

        Partially parsed configurations are remembered so that they will 
be deallocated when the entire struct usb_device is freed.

Alan Stern


# This is a BitKeeper generated patch for the following project:
# Project Name: greg k-h's linux 2.5 USB kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.1670  -> 1.1671 
#       drivers/usb/core/config.c       1.17    -> 1.18   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/09/15      [EMAIL PROTECTED]       1.1671
# Fix memory leaks and related errors:
#   Initialize interface->dev at the time it is allocated.
#   Don't call put_device() for unallocated interfaces.
#   Free the config->extra pointers.
#   Initialize the rawdescriptor pointers.
#   Remember partially-parsed configs so they can be freed.
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c Mon Sep 15 10:56:18 2003
+++ b/drivers/usb/core/config.c Mon Sep 15 10:56:18 2003
@@ -134,12 +134,6 @@
        interface->act_altsetting = 0;
        interface->num_altsetting = 0;
        interface->max_altsetting = USB_ALTSETTINGALLOC;
-       device_initialize(&interface->dev);
-       interface->dev.release = usb_release_intf;
-
-       /* put happens in usb_destroy_configuration */
-       get_device(&interface->dev);
-
        interface->altsetting = kmalloc(sizeof(*interface->altsetting) * 
interface->max_altsetting,
                                        GFP_KERNEL);
 
@@ -284,6 +278,7 @@
 int usb_parse_configuration(struct usb_host_config *config, char *buffer)
 {
        int i, size;
+       struct usb_interface *interface;
        int retval = -EINVAL;
        struct usb_descriptor_header *header;
 
@@ -296,18 +291,23 @@
 
        if (config->desc.bNumInterfaces > USB_MAXINTERFACES) {
                warn("too many interfaces");
-               goto error;
+               return -EINVAL;
        }
 
        for (i = 0; i < config->desc.bNumInterfaces; ++i) {
-               config->interface[i] = kmalloc(sizeof(struct usb_interface), 
GFP_KERNEL);
-               dbg("kmalloc IF %p, numif %i", config->interface[i], i);
-               if (!config->interface[i]) {
+               interface = config->interface[i] =
+                   kmalloc(sizeof(struct usb_interface), GFP_KERNEL);
+               dbg("kmalloc IF %p, numif %i", interface, i);
+               if (!interface) {
                        err("out of memory");
-                       retval = -ENOMEM;
-                       goto error;
+                       return -ENOMEM;
                }
-               memset(config->interface[i], 0x00, sizeof(struct usb_interface));
+               memset(interface, 0, sizeof(struct usb_interface));
+               interface->dev.release = usb_release_intf;
+               device_initialize(&interface->dev);
+
+               /* put happens in usb_destroy_configuration */
+               get_device(&interface->dev);
        }
 
        buffer += config->desc.bLength;
@@ -376,10 +376,6 @@
        }
 
        return size;
-error:
-       for (i = 0; i < USB_MAXINTERFACES; ++i)
-               kfree(config->interface[i]);
-       return retval;
 }
 
 // hub-only!! ... and only exported for reset/reinit path.
@@ -401,13 +397,13 @@
        for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
                struct usb_host_config *cf = &dev->config[c];
 
-               if (!cf->interface)
-                       break;
-
                for (i = 0; i < cf->desc.bNumInterfaces; i++) {
                        struct usb_interface *ifp = cf->interface[i];
-                       put_device(&ifp->dev);
+
+                       if (ifp)
+                               put_device(&ifp->dev);
                }
+               kfree(cf->extra);
        }
        kfree(dev->config);
 }
@@ -449,6 +445,7 @@
                err("out of memory");
                return -ENOMEM;
        }
+       memset(dev->rawdescriptors, 0, sizeof(char *) * 
dev->descriptor.bNumConfigurations);
 
        buffer = kmalloc(8, GFP_KERNEL);
        if (!buffer) {
@@ -502,7 +499,7 @@
                if (result > 0)
                        dbg("descriptor data left");
                else if (result < 0) {
-                       result = -EINVAL;
+                       ++cfgno;
                        goto err;
                }
        }




-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to