summaryrefslogtreecommitdiff
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-15 10:24:55 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-15 10:24:55 -0800
commite29876723f7cb7728f0d6a674d23f92673e9f112 (patch)
treeea1da8bf77139f6cc6de029988208a7eddaf2002 /drivers/usb/class/cdc-acm.c
parent8c988ae787af4900bec5410658e8a82844185c85 (diff)
parent4d4bac4499e9955521af80198063ef9c2f2bd634 (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.c54
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,