diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 10:24:55 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 10:24:55 -0800 |
commit | e29876723f7cb7728f0d6a674d23f92673e9f112 (patch) | |
tree | ea1da8bf77139f6cc6de029988208a7eddaf2002 /drivers/usb/class/cdc-acm.c | |
parent | 8c988ae787af4900bec5410658e8a82844185c85 (diff) | |
parent | 4d4bac4499e9955521af80198063ef9c2f2bd634 (diff) |
Merge tag 'usb-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB patches from Greg KH:
"Here's the big pull request for the USB driver tree for 3.20-rc1.
Nothing major happening here, just lots of gadget driver updates, new
device ids, and a bunch of cleanups.
All of these have been in linux-next for a while with no reported
issues"
* tag 'usb-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (299 commits)
usb: musb: fix device hotplug behind hub
usb: dwc2: Fix a bug in reading the endpoint directions from reg.
staging: emxx_udc: fix the build error
usb: Retry port status check on resume to work around RH bugs
Revert "usb: Reset USB-3 devices on USB-3 link bounce"
uhci-hub: use HUB_CHAR_*
usb: kconfig: replace PPC_OF with PPC
ehci-pci: disable for Intel MID platforms (update)
usb: gadget: Kconfig: use bool instead of boolean
usb: musb: blackfin: remove incorrect __exit_p()
USB: fix use-after-free bug in usb_hcd_unlink_urb()
ehci-pci: disable for Intel MID platforms
usb: host: pci_quirks: joing string literals
USB: add flag for HCDs that can't receive wakeup requests (isp1760-hcd)
USB: usbfs: allow URBs to be reaped after disconnection
cdc-acm: kill unnecessary messages
cdc-acm: add sanity checks
usb: phy: phy-generic: Fix USB PHY gpio reset
usb: dwc2: fix USB core dependencies
usb: renesas_usbhs: fix NULL pointer dereference in dma_release_channel()
...
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 546a17e8ad5b..e78720b59d67 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1091,6 +1091,7 @@ static int acm_probe(struct usb_interface *intf, unsigned long quirks; int num_rx_buf; int i; + unsigned int elength = 0; int combined_interfaces = 0; struct device *tty_dev; int rv = -ENOMEM; @@ -1136,9 +1137,12 @@ static int acm_probe(struct usb_interface *intf, dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; } + elength = buffer[0]; switch (buffer[2]) { case USB_CDC_UNION_TYPE: /* we've found it */ + if (elength < sizeof(struct usb_cdc_union_desc)) + goto next_desc; if (union_header) { dev_err(&intf->dev, "More than one " "union descriptor, skipping ...\n"); @@ -1147,29 +1151,36 @@ static int acm_probe(struct usb_interface *intf, union_header = (struct usb_cdc_union_desc *)buffer; break; case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/ + if (elength < sizeof(struct usb_cdc_country_functional_desc)) + goto next_desc; cfd = (struct usb_cdc_country_functional_desc *)buffer; break; case USB_CDC_HEADER_TYPE: /* maybe check version */ break; /* for now we ignore it */ case USB_CDC_ACM_TYPE: + if (elength < 4) + goto next_desc; ac_management_function = buffer[3]; break; case USB_CDC_CALL_MANAGEMENT_TYPE: + if (elength < 5) + goto next_desc; call_management_function = buffer[3]; call_interface_num = buffer[4]; break; default: - /* there are LOTS more CDC descriptors that + /* + * there are LOTS more CDC descriptors that * could legitimately be found here. */ dev_dbg(&intf->dev, "Ignoring descriptor: " - "type %02x, length %d\n", - buffer[2], buffer[0]); + "type %02x, length %ud\n", + buffer[2], elength); break; } next_desc: - buflen -= buffer[0]; - buffer += buffer[0]; + buflen -= elength; + buffer += elength; } if (!union_header) { @@ -1287,10 +1298,8 @@ made_compressed_probe: dev_dbg(&intf->dev, "interfaces are valid\n"); acm = kzalloc(sizeof(struct acm), GFP_KERNEL); - if (acm == NULL) { - dev_err(&intf->dev, "out of memory (acm kzalloc)\n"); + if (acm == NULL) goto alloc_fail; - } minor = acm_alloc_minor(acm); if (minor == ACM_TTY_MINORS) { @@ -1329,42 +1338,32 @@ made_compressed_probe: acm->quirks = quirks; buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); - if (!buf) { - dev_err(&intf->dev, "out of memory (ctrl buffer alloc)\n"); + if (!buf) goto alloc_fail2; - } acm->ctrl_buffer = buf; - if (acm_write_buffers_alloc(acm) < 0) { - dev_err(&intf->dev, "out of memory (write buffer alloc)\n"); + if (acm_write_buffers_alloc(acm) < 0) goto alloc_fail4; - } acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); - if (!acm->ctrlurb) { - dev_err(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); + if (!acm->ctrlurb) goto alloc_fail5; - } + for (i = 0; i < num_rx_buf; i++) { struct acm_rb *rb = &(acm->read_buffers[i]); struct urb *urb; rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, &rb->dma); - if (!rb->base) { - dev_err(&intf->dev, "out of memory " - "(read bufs usb_alloc_coherent)\n"); + if (!rb->base) goto alloc_fail6; - } rb->index = i; rb->instance = acm; urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - dev_err(&intf->dev, - "out of memory (read urbs usb_alloc_urb)\n"); + if (!urb) goto alloc_fail6; - } + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; urb->transfer_dma = rb->dma; if (acm->is_int_ep) { @@ -1389,11 +1388,8 @@ made_compressed_probe: struct acm_wb *snd = &(acm->wb[i]); snd->urb = usb_alloc_urb(0, GFP_KERNEL); - if (snd->urb == NULL) { - dev_err(&intf->dev, - "out of memory (write urbs usb_alloc_urb)\n"); + if (snd->urb == NULL) goto alloc_fail7; - } if (usb_endpoint_xfer_int(epwrite)) usb_fill_int_urb(snd->urb, usb_dev, |