ChangeSet 1.1595.7.1, 2003/07/29 11:36:46-07:00, [EMAIL PROTECTED]
[PATCH] USB: fix stupid kobject coding error with regards to struct usb_interface
Added a release callback, as is required, otherwise we can easily oops
if a user grabs a sysfs file and the device is removed from the system.
drivers/usb/core/config.c | 94 +++++++++++++++++++++++++---------------------
include/linux/usb.h | 5 +-
2 files changed, 57 insertions(+), 42 deletions(-)
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c Fri Aug 1 10:57:02 2003
+++ b/drivers/usb/core/config.c Fri Aug 1 10:57:02 2003
@@ -98,6 +98,32 @@
return parsed;
}
+static void usb_release_intf(struct device *dev)
+{
+ struct usb_interface *intf;
+ int j;
+ int k;
+
+ intf = to_usb_interface(dev);
+
+ if (intf->altsetting) {
+ for (j = 0; j < intf->num_altsetting; j++) {
+ struct usb_host_interface *as = &intf->altsetting[j];
+ if (as->extra)
+ kfree(as->extra);
+
+ if (as->endpoint) {
+ for (k = 0; k < as->desc.bNumEndpoints; k++)
+ if (as->endpoint[k].extra)
+ kfree(as->endpoint[k].extra);
+ kfree(as->endpoint);
+ }
+ }
+ kfree(intf->altsetting);
+ }
+ kfree(intf);
+}
+
static int usb_parse_interface(struct usb_interface *interface, unsigned char
*buffer, int size)
{
int i, len, numskipped, retval, parsed = 0;
@@ -109,7 +135,11 @@
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);
@@ -253,30 +283,33 @@
int usb_parse_configuration(struct usb_host_config *config, char *buffer)
{
- int i, retval, size;
+ int i, size;
+ int retval = -EINVAL;
struct usb_descriptor_header *header;
memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
le16_to_cpus(&config->desc.wTotalLength);
size = config->desc.wTotalLength;
+ for (i = 0; i < USB_MAXINTERFACES; ++i)
+ config->interface[i] = NULL;
+
if (config->desc.bNumInterfaces > USB_MAXINTERFACES) {
warn("too many interfaces");
- return -1;
+ goto error;
}
- config->interface = (struct usb_interface *)
- kmalloc(config->desc.bNumInterfaces *
- sizeof(struct usb_interface), GFP_KERNEL);
- dbg("kmalloc IF %p, numif %i", config->interface, config->desc.bNumInterfaces);
- if (!config->interface) {
- err("out of memory");
- return -1;
+ 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]) {
+ err("out of memory");
+ retval = -ENOMEM;
+ goto error;
+ }
+ memset(config->interface[i], 0x00, sizeof(struct usb_interface));
}
- memset(config->interface, 0,
- config->desc.bNumInterfaces * sizeof(struct usb_interface));
-
buffer += config->desc.bLength;
size -= config->desc.bLength;
@@ -334,7 +367,7 @@
}
}
- retval = usb_parse_interface(config->interface + i, buffer, size);
+ retval = usb_parse_interface(config->interface[i], buffer, size);
if (retval < 0)
return retval;
@@ -343,13 +376,17 @@
}
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.
// otherwise used internally on disconnect/destroy path
void usb_destroy_configuration(struct usb_device *dev)
{
- int c, i, j, k;
+ int c, i;
if (!dev->config)
return;
@@ -368,34 +405,9 @@
break;
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
- struct usb_interface *ifp =
- &cf->interface[i];
-
- if (!ifp->altsetting)
- break;
-
- for (j = 0; j < ifp->num_altsetting; j++) {
- struct usb_host_interface *as =
- &ifp->altsetting[j];
-
- if(as->extra) {
- kfree(as->extra);
- }
-
- if (!as->endpoint)
- break;
-
- for(k = 0; k < as->desc.bNumEndpoints; k++) {
- if(as->endpoint[k].extra) {
- kfree(as->endpoint[k].extra);
- }
- }
- kfree(as->endpoint);
- }
-
- kfree(ifp->altsetting);
+ struct usb_interface *ifp = cf->interface[i];
+ put_device(&ifp->dev);
}
- kfree(cf->interface);
}
kfree(dev->config);
}
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h Fri Aug 1 10:57:02 2003
+++ b/include/linux/usb.h Fri Aug 1 10:57:02 2003
@@ -140,6 +140,9 @@
dev_set_drvdata(&intf->dev, data);
}
+/* this maximum is arbitrary */
+#define USB_MAXINTERFACES 32
+
/* USB_DT_CONFIG: Configuration descriptor information.
*
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
@@ -153,7 +156,7 @@
/* the interfaces associated with this configuration
* these will be in numeric order, 0..desc.bNumInterfaces
*/
- struct usb_interface *interface;
+ struct usb_interface *interface[USB_MAXINTERFACES];
unsigned char *extra; /* Extra descriptors */
int extralen;
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel