On Mon, 21 Oct 2013, Huang Rui wrote:

> In Test 9 of usbtest module, it is used for performing chapter 9 tests N
> times.
> 
> USB2.0 Extension descriptor is one of the generic device-level capbility
> descriptors which added in section 9.6.2.1 of USB 3.0 spec.
> 
> This patch adds to support getting usb2.0 extension descriptor test
> scenario for USB 3.0.
> 
> Signed-off-by: Huang Rui <ray.hu...@amd.com>

...

> @@ -694,12 +716,56 @@ static int ch9_postconfig(struct usbtest_dev *dev)
>        * 3.0 spec
>        */
>       if (le16_to_cpu(udev->descriptor.bcdUSB) == 0x0300) {
> +             struct usb_bos_descriptor *bos = NULL;
> +             struct usb_dev_cap_header *header = NULL;
> +             unsigned total, num, length;
> +
>               retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf,
>                               sizeof(*udev->bos->desc));
>               if (retval != sizeof(*udev->bos->desc)) {
>                       dev_err(&iface->dev, "bos descriptor --> %d\n", retval);
>                       return (retval < 0) ? retval : -EDOM;
>               }
> +
> +             bos = (struct usb_bos_descriptor *)dev->buf;
> +             total = le16_to_cpu(bos->wTotalLength);
> +             num = bos->bNumDeviceCaps;
> +
> +             /*
> +              * get generic device-level capability descriptors [9.6.2]
> +              * in USB 3.0 spec
> +              */
> +             retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf,
> +                             total);

This exposes the kernel to a buffer overflow bug.  Remember, dev->buf
is only 256 bytes long.  What happens if total > 256?

> +             if (retval != total) {
> +                     dev_err(&iface->dev, "bos descriptor set --> %d\n",
> +                                     retval);
> +                     return (retval < 0) ? retval : -EDOM;
> +             }
> +
> +             length = sizeof(*udev->bos->desc);
> +             for (i = 0; i < num; i++) {
> +                     dev->buf += length;

What will happen when the code further down uses dev->buf to hold
config descriptors?  You should use a local pointer here; don't change
dev->buf.

What happens if the new value of the pointer lies beyond the end of the 
dev->buf?

> +                     header = (struct usb_dev_cap_header *)dev->buf;
> +                     length = header->bLength;
> +
> +                     if (header->bDescriptorType !=
> +                                     USB_DT_DEVICE_CAPABILITY) {
> +                             dev_warn(&udev->dev, "not device capability 
> descriptor, skip\n");
> +                             continue;
> +                     }
> +
> +                     switch (header->bDevCapabilityType) {
> +                     case USB_CAP_TYPE_EXT:
> +                             if (!is_good_ext(dev)) {

What happens if header points to a location only 1 or 2 bytes before 
the end of dev->buf?

> +                                     dev_err(&iface->dev, "bogus usb 2.0 
> extension descriptor\n");
> +                                     return -EDOM;
> +                             }
> +                             break;
> +                     default:
> +                             break;
> +                     }
> +             }
>       }

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to