3.2.100-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Masakazu Mokuno <masakazu.mokuno@xxxxxxxxx> commit 81cf4a45360f70528f1f64ba018d61cb5767249a upstream. As most of BOS descriptors are longer in length than their header 'struct usb_dev_cap_header', comparing solely with it is not sufficient to avoid out-of-bounds access to BOS descriptors. This patch adds descriptor type specific length check in usb_get_bos_descriptor() to fix the issue. Signed-off-by: Masakazu Mokuno <masakazu.mokuno@xxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> [bwh: Backported to 3.2: - Drop handling of USB_PTM_CAP_TYPE and USB_SSP_CAP_TYPE - Adjust filename] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -878,6 +878,13 @@ void usb_release_bos_descriptor(struct u } } +static const __u8 bos_desc_len[256] = { + [USB_CAP_TYPE_WIRELESS_USB] = USB_DT_USB_WIRELESS_CAP_SIZE, + [USB_CAP_TYPE_EXT] = USB_DT_USB_EXT_CAP_SIZE, + [USB_SS_CAP_TYPE] = USB_DT_USB_SS_CAP_SIZE, + [CONTAINER_ID_TYPE] = USB_DT_USB_SS_CONTN_ID_SIZE, +}; + /* Get BOS descriptor set */ int usb_get_bos_descriptor(struct usb_device *dev) { @@ -886,6 +893,7 @@ int usb_get_bos_descriptor(struct usb_de struct usb_dev_cap_header *cap; unsigned char *buffer; int length, total_len, num, i; + __u8 cap_type; int ret; bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL); @@ -938,7 +946,13 @@ int usb_get_bos_descriptor(struct usb_de dev->bos->desc->bNumDeviceCaps = i; break; } + cap_type = cap->bDevCapabilityType; length = cap->bLength; + if (bos_desc_len[cap_type] && length < bos_desc_len[cap_type]) { + dev->bos->desc->bNumDeviceCaps = i; + break; + } + total_len -= length; if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { @@ -946,7 +960,7 @@ int usb_get_bos_descriptor(struct usb_de continue; } - switch (cap->bDevCapabilityType) { + switch (cap_type) { case USB_CAP_TYPE_WIRELESS_USB: /* Wireless USB cap descriptor is handled by wusb */ break; --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -800,6 +800,8 @@ struct usb_wireless_cap_descriptor { /* __u8 bReserved; } __attribute__((packed)); +#define USB_DT_USB_WIRELESS_CAP_SIZE 11 + /* USB 2.0 Extension descriptor */ #define USB_CAP_TYPE_EXT 2