diff options
Diffstat (limited to 'drivers/usb/core/config.c')
| -rw-r--r-- | drivers/usb/core/config.c | 22 | 
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 4be52c602e9b..883549ee946c 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -643,15 +643,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,  		} else if (header->bDescriptorType ==  				USB_DT_INTERFACE_ASSOCIATION) { +			struct usb_interface_assoc_descriptor *d; + +			d = (struct usb_interface_assoc_descriptor *)header; +			if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) { +				dev_warn(ddev, +					 "config %d has an invalid interface association descriptor of length %d, skipping\n", +					 cfgno, d->bLength); +				continue; +			} +  			if (iad_num == USB_MAXIADS) {  				dev_warn(ddev, "found more Interface "  					       "Association Descriptors "  					       "than allocated for in "  					       "configuration %d\n", cfgno);  			} else { -				config->intf_assoc[iad_num] = -					(struct usb_interface_assoc_descriptor -					*)header; +				config->intf_assoc[iad_num] = d;  				iad_num++;  			} @@ -852,7 +860,7 @@ int usb_get_configuration(struct usb_device *dev)  		}  		if (dev->quirks & USB_QUIRK_DELAY_INIT) -			msleep(100); +			msleep(200);  		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,  		    bigbuffer, length); @@ -952,10 +960,12 @@ int usb_get_bos_descriptor(struct usb_device *dev)  	for (i = 0; i < num; i++) {  		buffer += length;  		cap = (struct usb_dev_cap_header *)buffer; -		length = cap->bLength; -		if (total_len < length) +		if (total_len < sizeof(*cap) || total_len < cap->bLength) { +			dev->bos->desc->bNumDeviceCaps = i;  			break; +		} +		length = cap->bLength;  		total_len -= length;  		if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {  |