Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd7a3fe7 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

USB: fix out-of-bounds in usb_set_configuration



Andrey Konovalov reported a possible out-of-bounds problem for a USB interface
association descriptor.  He writes:
	It seems there's no proper size check of a USB_DT_INTERFACE_ASSOCIATION
	descriptor. It's only checked that the size is >= 2 in
	usb_parse_configuration(), so find_iad() might do out-of-bounds access
	to intf_assoc->bInterfaceCount.

And he's right, we don't check for crazy descriptors of this type very well, so
resolve this problem.  Yet another issue found by syzkaller...

Reported-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Tested-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bcd6a7aa
Loading
Loading
Loading
Loading
+11 −3
Original line number Original line Diff line number Diff line
@@ -643,15 +643,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,


		} else if (header->bDescriptorType ==
		} else if (header->bDescriptorType ==
				USB_DT_INTERFACE_ASSOCIATION) {
				USB_DT_INTERFACE_ASSOCIATION) {
			struct usb_interface_assoc_descriptor *d;

			d = (struct usb_interface_assoc_descriptor *)header;
			if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) {
				dev_warn(ddev,
					 "config %d has an invalid interface association descriptor of length %d, skipping\n",
					 cfgno, d->bLength);
				continue;
			}

			if (iad_num == USB_MAXIADS) {
			if (iad_num == USB_MAXIADS) {
				dev_warn(ddev, "found more Interface "
				dev_warn(ddev, "found more Interface "
					       "Association Descriptors "
					       "Association Descriptors "
					       "than allocated for in "
					       "than allocated for in "
					       "configuration %d\n", cfgno);
					       "configuration %d\n", cfgno);
			} else {
			} else {
				config->intf_assoc[iad_num] =
				config->intf_assoc[iad_num] = d;
					(struct usb_interface_assoc_descriptor
					*)header;
				iad_num++;
				iad_num++;
			}
			}


+1 −0
Original line number Original line Diff line number Diff line
@@ -780,6 +780,7 @@ struct usb_interface_assoc_descriptor {
	__u8  iFunction;
	__u8  iFunction;
} __attribute__ ((packed));
} __attribute__ ((packed));


#define USB_DT_INTERFACE_ASSOCIATION_SIZE	8


/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/