diff options
author | Mathias Payer <mathias.payer@nebelwelt.net> | 2018-12-05 15:19:59 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-12-05 15:20:14 -0500 |
commit | 704620afc70cf47abb9d6a1a57f3825d2bca49cf (patch) | |
tree | e8e4e4bcb5003f847518a2ef0669895a6b241eda | |
parent | 2f2dde6ba89b1ef1fe23c1138131b315d9aa4019 (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.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/hwa-hc.c | 2 | ||||
-rw-r--r-- | include/linux/usb.h | 4 |
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 | ||
834 | int __usb_get_extra_descriptor(char *buffer, unsigned size, | 834 | int __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 | ||
409 | int __usb_get_extra_descriptor(char *buffer, unsigned size, | 409 | int __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 | ||