Commit d61741ad authored by Mathias Payer's avatar Mathias Payer Committed by Kleber Sacilotto de Souza

USB: check usb_get_extra_descriptor for proper size

BugLink: https://bugs.launchpad.net/bugs/1811077

commit 704620af upstream.

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: default avatarHui Peng <benquike@gmail.com>
Reported-by: default avatarMathias Payer <mathias.payer@nebelwelt.net>
Co-developed-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarHui Peng <benquike@gmail.com>
Signed-off-by: default avatarMathias Payer <mathias.payer@nebelwelt.net>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 0643f7c9
...@@ -2225,7 +2225,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev) ...@@ -2225,7 +2225,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
/* descriptor may appear anywhere in config */ /* descriptor may appear anywhere in config */
err = __usb_get_extra_descriptor(udev->rawdescriptors[0], err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
le16_to_cpu(udev->config[0].desc.wTotalLength), le16_to_cpu(udev->config[0].desc.wTotalLength),
USB_DT_OTG, (void **) &desc); USB_DT_OTG, (void **) &desc, sizeof(*desc));
if (err || !(desc->bmAttributes & USB_OTG_HNP)) if (err || !(desc->bmAttributes & USB_OTG_HNP))
return 0; return 0;
......
...@@ -678,14 +678,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number); ...@@ -678,14 +678,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number);
*/ */
int __usb_get_extra_descriptor(char *buffer, unsigned size, int __usb_get_extra_descriptor(char *buffer, unsigned size,
unsigned char type, void **ptr) unsigned char type, void **ptr, size_t minsize)
{ {
struct usb_descriptor_header *header; struct usb_descriptor_header *header;
while (size >= sizeof(struct usb_descriptor_header)) { while (size >= sizeof(struct usb_descriptor_header)) {
header = (struct usb_descriptor_header *)buffer; header = (struct usb_descriptor_header *)buffer;
if (header->bLength < 2) { if (header->bLength < 2 || header->bLength > size) {
printk(KERN_ERR printk(KERN_ERR
"%s: bogus descriptor, type %d length %d\n", "%s: bogus descriptor, type %d length %d\n",
usbcore_name, usbcore_name,
...@@ -694,7 +694,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, ...@@ -694,7 +694,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
return -1; return -1;
} }
if (header->bDescriptorType == type) { if (header->bDescriptorType == type && header->bLength >= minsize) {
*ptr = header; *ptr = header;
return 0; return 0;
} }
......
...@@ -654,7 +654,7 @@ static int hwahc_security_create(struct hwahc *hwahc) ...@@ -654,7 +654,7 @@ static int hwahc_security_create(struct hwahc *hwahc)
top = itr + itr_size; top = itr + itr_size;
result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index], result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index],
le16_to_cpu(usb_dev->actconfig->desc.wTotalLength), le16_to_cpu(usb_dev->actconfig->desc.wTotalLength),
USB_DT_SECURITY, (void **) &secd); USB_DT_SECURITY, (void **) &secd, sizeof(*secd));
if (result == -1) { if (result == -1) {
dev_warn(dev, "BUG? WUSB host has no security descriptors\n"); dev_warn(dev, "BUG? WUSB host has no security descriptors\n");
return 0; return 0;
......
...@@ -336,11 +336,11 @@ struct usb_host_bos { ...@@ -336,11 +336,11 @@ struct usb_host_bos {
}; };
int __usb_get_extra_descriptor(char *buffer, unsigned size, int __usb_get_extra_descriptor(char *buffer, unsigned size,
unsigned char type, void **ptr); unsigned char type, void **ptr, size_t min);
#define usb_get_extra_descriptor(ifpoint, type, ptr) \ #define usb_get_extra_descriptor(ifpoint, type, ptr) \
__usb_get_extra_descriptor((ifpoint)->extra, \ __usb_get_extra_descriptor((ifpoint)->extra, \
(ifpoint)->extralen, \ (ifpoint)->extralen, \
type, (void **)ptr) type, (void **)ptr, sizeof(**(ptr)))
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment