diff options
author | Oliver Neukum <oliver@neukum.org> | 2009-04-20 11:24:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-04-23 17:15:30 -0400 |
commit | 052fbc0d7f76106725c998183d64dcacecd21f8f (patch) | |
tree | 0771141a48c604ddbfdd1dca3a19bf2c37523876 /drivers/usb/class/cdc-wdm.c | |
parent | 2400a2bfbd0e912193fe3b077f492d4980141813 (diff) |
USB: correct error handling in cdc-wdm
This patch to cdc-wdm
- checks for partial extra descriptors
- fixes a leak in the error case of probe
- checks for an exact number of endpoints
- adds a clarifying comment
Signed-off-by: Oliver Neukum <oliver@neukum.org>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/class/cdc-wdm.c')
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 34e6108e1d42..0fe434505ac4 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * This driver supports USB CDC WCM Device Management. | 4 | * This driver supports USB CDC WCM Device Management. |
5 | * | 5 | * |
6 | * Copyright (c) 2007-2008 Oliver Neukum | 6 | * Copyright (c) 2007-2009 Oliver Neukum |
7 | * | 7 | * |
8 | * Some code taken from cdc-acm.c | 8 | * Some code taken from cdc-acm.c |
9 | * | 9 | * |
@@ -610,7 +610,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
610 | if (!buffer) | 610 | if (!buffer) |
611 | goto out; | 611 | goto out; |
612 | 612 | ||
613 | while (buflen > 0) { | 613 | while (buflen > 2) { |
614 | if (buffer [1] != USB_DT_CS_INTERFACE) { | 614 | if (buffer [1] != USB_DT_CS_INTERFACE) { |
615 | dev_err(&intf->dev, "skipping garbage\n"); | 615 | dev_err(&intf->dev, "skipping garbage\n"); |
616 | goto next_desc; | 616 | goto next_desc; |
@@ -646,16 +646,18 @@ next_desc: | |||
646 | spin_lock_init(&desc->iuspin); | 646 | spin_lock_init(&desc->iuspin); |
647 | init_waitqueue_head(&desc->wait); | 647 | init_waitqueue_head(&desc->wait); |
648 | desc->wMaxCommand = maxcom; | 648 | desc->wMaxCommand = maxcom; |
649 | /* this will be expanded and needed in hardware endianness */ | ||
649 | desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber); | 650 | desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber); |
650 | desc->intf = intf; | 651 | desc->intf = intf; |
651 | INIT_WORK(&desc->rxwork, wdm_rxwork); | 652 | INIT_WORK(&desc->rxwork, wdm_rxwork); |
652 | 653 | ||
653 | iface = &intf->altsetting[0]; | 654 | rv = -EINVAL; |
655 | iface = intf->cur_altsetting; | ||
656 | if (iface->desc.bNumEndpoints != 1) | ||
657 | goto err; | ||
654 | ep = &iface->endpoint[0].desc; | 658 | ep = &iface->endpoint[0].desc; |
655 | if (!ep || !usb_endpoint_is_int_in(ep)) { | 659 | if (!ep || !usb_endpoint_is_int_in(ep)) |
656 | rv = -EINVAL; | ||
657 | goto err; | 660 | goto err; |
658 | } | ||
659 | 661 | ||
660 | desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize); | 662 | desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize); |
661 | desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; | 663 | desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; |
@@ -711,12 +713,19 @@ next_desc: | |||
711 | 713 | ||
712 | usb_set_intfdata(intf, desc); | 714 | usb_set_intfdata(intf, desc); |
713 | rv = usb_register_dev(intf, &wdm_class); | 715 | rv = usb_register_dev(intf, &wdm_class); |
714 | dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n", | ||
715 | intf->minor - WDM_MINOR_BASE); | ||
716 | if (rv < 0) | 716 | if (rv < 0) |
717 | goto err; | 717 | goto err3; |
718 | else | ||
719 | dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n", | ||
720 | intf->minor - WDM_MINOR_BASE); | ||
718 | out: | 721 | out: |
719 | return rv; | 722 | return rv; |
723 | err3: | ||
724 | usb_set_intfdata(intf, NULL); | ||
725 | usb_buffer_free(interface_to_usbdev(desc->intf), | ||
726 | desc->bMaxPacketSize0, | ||
727 | desc->inbuf, | ||
728 | desc->response->transfer_dma); | ||
720 | err2: | 729 | err2: |
721 | usb_buffer_free(interface_to_usbdev(desc->intf), | 730 | usb_buffer_free(interface_to_usbdev(desc->intf), |
722 | desc->wMaxPacketSize, | 731 | desc->wMaxPacketSize, |