ChangeSet 1.1315.8.21, 2003/09/17 17:08:46-07:00, [EMAIL PROTECTED]

[PATCH] USB: Changes to core/config.c (2 of 9)

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.


 drivers/usb/core/config.c |   41 +++++++++++++++++++----------------------
 1 files changed, 19 insertions(+), 22 deletions(-)


diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c Fri Sep 19 17:10:34 2003
+++ b/drivers/usb/core/config.c Fri Sep 19 17:10:34 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