aboutsummaryrefslogtreecommitdiff
path: root/common/usb.c
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2012-07-24 07:12:02 +0000
committerMarek Vasut <marex@denx.de>2012-10-22 08:25:07 +0200
commit8b8d779dacc149be0607dfc1b399bbdb62e57108 (patch)
tree7198df8ddee428b5cf7094fb401db53958f3b65f /common/usb.c
parente81e79ede1aa1052735b9ee9a364f99b93605a08 (diff)
usb: fallback safely when a configuration descriptor is too large
When a USB configuration descriptor was larger than our USB buffer (512 bytes), we were skipping the full descriptor reading but then we were still parsing and using it, triggering memory corruptions. Now in that case, it just skips this device enumeration and displays the appropriate message to the user, so he can fix the buffer if he wants. This bug was triggered by some UVC webcams which have very large configuration descriptors (e.g. a couple of kB) describing all their supported video encodings. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> Acked-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common/usb.c')
-rw-r--r--common/usb.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/common/usb.c b/common/usb.c
index 1c9763cb6..50b81752e 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -508,8 +508,8 @@ int usb_get_configuration_no(struct usb_device *dev,
tmp = le16_to_cpu(config->wTotalLength);
if (tmp > USB_BUFSIZ) {
- USB_PRINTF("usb_get_configuration_no: failed to get " \
- "descriptor - too long: %d\n", tmp);
+ printf("usb_get_configuration_no: failed to get " \
+ "descriptor - too long: %d\n", tmp);
return -1;
}
@@ -946,7 +946,13 @@ int usb_new_device(struct usb_device *dev)
le16_to_cpus(&dev->descriptor.idProduct);
le16_to_cpus(&dev->descriptor.bcdDevice);
/* only support for one config for now */
- usb_get_configuration_no(dev, tmpbuf, 0);
+ err = usb_get_configuration_no(dev, tmpbuf, 0);
+ if (err < 0) {
+ printf("usb_new_device: Cannot read configuration, " \
+ "skipping device %04x:%04x\n",
+ dev->descriptor.idVendor, dev->descriptor.idProduct);
+ return -1;
+ }
usb_parse_config(dev, tmpbuf, 0);
usb_set_maxpacket(dev);
/* we set the default configuration here */