summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Payer <mathias.payer@nebelwelt.net>2018-12-05 15:19:59 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-12-05 15:20:14 -0500
commit704620afc70cf47abb9d6a1a57f3825d2bca49cf (patch)
treee8e4e4bcb5003f847518a2ef0669895a6b241eda
parent2f2dde6ba89b1ef1fe23c1138131b315d9aa4019 (diff)
USB: check usb_get_extra_descriptor for proper size
When reading an extra descriptor, we need to properly check the minimum and maximum size allowed, to prevent from invalid data being sent by a device. Reported-by: Hui Peng <benquike@gmail.com> Reported-by: Mathias Payer <mathias.payer@nebelwelt.net> Co-developed-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Hui Peng <benquike@gmail.com> Signed-off-by: Mathias Payer <mathias.payer@nebelwelt.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/core/usb.c6
-rw-r--r--drivers/usb/host/hwa-hc.c2
-rw-r--r--include/linux/usb.h4
4 files changed, 7 insertions, 7 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 528664059a12..f76b2e0aba9d 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2251,7 +2251,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
2251 /* descriptor may appear anywhere in config */ 2251 /* descriptor may appear anywhere in config */
2252 err = __usb_get_extra_descriptor(udev->rawdescriptors[0], 2252 err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
2253 le16_to_cpu(udev->config[0].desc.wTotalLength), 2253 le16_to_cpu(udev->config[0].desc.wTotalLength),
2254 USB_DT_OTG, (void **) &desc); 2254 USB_DT_OTG, (void **) &desc, sizeof(*desc));
2255 if (err || !(desc->bmAttributes & USB_OTG_HNP)) 2255 if (err || !(desc->bmAttributes & USB_OTG_HNP))
2256 return 0; 2256 return 0;
2257 2257
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 79d8bd7a612e..4ebfbd737905 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -832,14 +832,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number);
832 */ 832 */
833 833
834int __usb_get_extra_descriptor(char *buffer, unsigned size, 834int __usb_get_extra_descriptor(char *buffer, unsigned size,
835 unsigned char type, void **ptr) 835 unsigned char type, void **ptr, size_t minsize)
836{ 836{
837 struct usb_descriptor_header *header; 837 struct usb_descriptor_header *header;
838 838
839 while (size >= sizeof(struct usb_descriptor_header)) { 839 while (size >= sizeof(struct usb_descriptor_header)) {
840 header = (struct usb_descriptor_header *)buffer; 840 header = (struct usb_descriptor_header *)buffer;
841 841
842 if (header->bLength < 2) { 842 if (header->bLength < 2 || header->bLength > size) {
843 printk(KERN_ERR 843 printk(KERN_ERR
844 "%s: bogus descriptor, type %d length %d\n", 844 "%s: bogus descriptor, type %d length %d\n",
845 usbcore_name, 845 usbcore_name,
@@ -848,7 +848,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
848 return -1; 848 return -1;
849 } 849 }
850 850
851 if (header->bDescriptorType == type) { 851 if (header->bDescriptorType == type && header->bLength >= minsize) {
852 *ptr = header; 852 *ptr = header;
853 return 0; 853 return 0;
854 } 854 }
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index 684d6f074c3a..09a8ebd95588 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -640,7 +640,7 @@ static int hwahc_security_create(struct hwahc *hwahc)
640 top = itr + itr_size; 640 top = itr + itr_size;
641 result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index], 641 result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index],
642 le16_to_cpu(usb_dev->actconfig->desc.wTotalLength), 642 le16_to_cpu(usb_dev->actconfig->desc.wTotalLength),
643 USB_DT_SECURITY, (void **) &secd); 643 USB_DT_SECURITY, (void **) &secd, sizeof(*secd));
644 if (result == -1) { 644 if (result == -1) {
645 dev_warn(dev, "BUG? WUSB host has no security descriptors\n"); 645 dev_warn(dev, "BUG? WUSB host has no security descriptors\n");
646 return 0; 646 return 0;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 4cdd515a4385..5e49e82c4368 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -407,11 +407,11 @@ struct usb_host_bos {
407}; 407};
408 408
409int __usb_get_extra_descriptor(char *buffer, unsigned size, 409int __usb_get_extra_descriptor(char *buffer, unsigned size,
410 unsigned char type, void **ptr); 410 unsigned char type, void **ptr, size_t min);
411#define usb_get_extra_descriptor(ifpoint, type, ptr) \ 411#define usb_get_extra_descriptor(ifpoint, type, ptr) \
412 __usb_get_extra_descriptor((ifpoint)->extra, \ 412 __usb_get_extra_descriptor((ifpoint)->extra, \
413 (ifpoint)->extralen, \ 413 (ifpoint)->extralen, \
414 type, (void **)ptr) 414 type, (void **)ptr, sizeof(**(ptr)))
415 415
416/* ----------------------------------------------------------------------- */ 416/* ----------------------------------------------------------------------- */
417 417