Commit 7b6e85da authored by Mathias Payer's avatar Mathias Payer Committed by Greg Kroah-Hartman

USB: check usb_get_extra_descriptor for proper size

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>
parent 810487aa
......@@ -2231,7 +2231,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
/* descriptor may appear anywhere in config */
err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
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))
return 0;
......
......@@ -833,14 +833,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number);
*/
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;
while (size >= sizeof(struct usb_descriptor_header)) {
header = (struct usb_descriptor_header *)buffer;
if (header->bLength < 2) {
if (header->bLength < 2 || header->bLength > size) {
printk(KERN_ERR
"%s: bogus descriptor, type %d length %d\n",
usbcore_name,
......@@ -849,7 +849,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
return -1;
}
if (header->bDescriptorType == type) {
if (header->bDescriptorType == type && header->bLength >= minsize) {
*ptr = header;
return 0;
}
......
......@@ -654,7 +654,7 @@ static int hwahc_security_create(struct hwahc *hwahc)
top = itr + itr_size;
result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index],
le16_to_cpu(usb_dev->actconfig->desc.wTotalLength),
USB_DT_SECURITY, (void **) &secd);
USB_DT_SECURITY, (void **) &secd, sizeof(*secd));
if (result == -1) {
dev_warn(dev, "BUG? WUSB host has no security descriptors\n");
return 0;
......
......@@ -407,11 +407,11 @@ struct usb_host_bos {
};
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) \
__usb_get_extra_descriptor((ifpoint)->extra, \
(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