USB: core: Add type-specific length check of BOS descriptors
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@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [bwh: Backported to 3.16: drop handling of USB_PTM_CAP_TYPE and USB_SSP_CAP_TYPE] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
This commit is contained in:
parent
5203cd7a0e
commit
ded0acf2fb
|
@ -852,6 +852,13 @@ void usb_release_bos_descriptor(struct usb_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -860,6 +867,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
|||
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);
|
||||
|
@ -912,7 +920,13 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
|||
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) {
|
||||
|
@ -920,7 +934,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
|||
continue;
|
||||
}
|
||||
|
||||
switch (cap->bDevCapabilityType) {
|
||||
switch (cap_type) {
|
||||
case USB_CAP_TYPE_WIRELESS_USB:
|
||||
/* Wireless USB cap descriptor is handled by wusb */
|
||||
break;
|
||||
|
|
|
@ -815,6 +815,8 @@ struct usb_wireless_cap_descriptor { /* Ultra Wide Band */
|
|||
__u8 bReserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_DT_USB_WIRELESS_CAP_SIZE 11
|
||||
|
||||
/* USB 2.0 Extension descriptor */
|
||||
#define USB_CAP_TYPE_EXT 2
|
||||
|
||||
|
|
Loading…
Reference in New Issue