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

Commit 903b2d14 authored by Masakazu Mokuno's avatar Masakazu Mokuno Committed by Greg Kroah-Hartman
Browse files

USB: core: Add type-specific length check of BOS descriptors



commit 81cf4a45 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: default avatarMasakazu Mokuno <masakazu.mokuno@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4346c775
Loading
Loading
Loading
Loading
+24 −4
Original line number Original line Diff line number Diff line
@@ -905,14 +905,25 @@ 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,
	[USB_SSP_CAP_TYPE]          = USB_DT_USB_SSP_CAP_SIZE(1),
	[CONTAINER_ID_TYPE]         = USB_DT_USB_SS_CONTN_ID_SIZE,
	[USB_PTM_CAP_TYPE]          = USB_DT_USB_PTM_ID_SIZE,
};

/* Get BOS descriptor set */
/* Get BOS descriptor set */
int usb_get_bos_descriptor(struct usb_device *dev)
int usb_get_bos_descriptor(struct usb_device *dev)
{
{
	struct device *ddev = &dev->dev;
	struct device *ddev = &dev->dev;
	struct usb_bos_descriptor *bos;
	struct usb_bos_descriptor *bos;
	struct usb_dev_cap_header *cap;
	struct usb_dev_cap_header *cap;
	struct usb_ssp_cap_descriptor *ssp_cap;
	unsigned char *buffer;
	unsigned char *buffer;
	int length, total_len, num, i;
	int length, total_len, num, i, ssac;
	__u8 cap_type;
	int ret;
	int ret;


	bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
	bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
@@ -965,7 +976,13 @@ int usb_get_bos_descriptor(struct usb_device *dev)
			dev->bos->desc->bNumDeviceCaps = i;
			dev->bos->desc->bNumDeviceCaps = i;
			break;
			break;
		}
		}
		cap_type = cap->bDevCapabilityType;
		length = cap->bLength;
		length = cap->bLength;
		if (bos_desc_len[cap_type] && length < bos_desc_len[cap_type]) {
			dev->bos->desc->bNumDeviceCaps = i;
			break;
		}

		total_len -= length;
		total_len -= length;


		if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
		if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
@@ -973,7 +990,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
			continue;
			continue;
		}
		}


		switch (cap->bDevCapabilityType) {
		switch (cap_type) {
		case USB_CAP_TYPE_WIRELESS_USB:
		case USB_CAP_TYPE_WIRELESS_USB:
			/* Wireless USB cap descriptor is handled by wusb */
			/* Wireless USB cap descriptor is handled by wusb */
			break;
			break;
@@ -986,8 +1003,11 @@ int usb_get_bos_descriptor(struct usb_device *dev)
				(struct usb_ss_cap_descriptor *)buffer;
				(struct usb_ss_cap_descriptor *)buffer;
			break;
			break;
		case USB_SSP_CAP_TYPE:
		case USB_SSP_CAP_TYPE:
			dev->bos->ssp_cap =
			ssp_cap = (struct usb_ssp_cap_descriptor *)buffer;
				(struct usb_ssp_cap_descriptor *)buffer;
			ssac = (le32_to_cpu(ssp_cap->bmAttributes) &
				USB_SSP_SUBLINK_SPEED_ATTRIBS) + 1;
			if (length >= USB_DT_USB_SSP_CAP_SIZE(ssac))
				dev->bos->ssp_cap = ssp_cap;
			break;
			break;
		case CONTAINER_ID_TYPE:
		case CONTAINER_ID_TYPE:
			dev->bos->ss_id =
			dev->bos->ss_id =
+3 −0
Original line number Original line Diff line number Diff line
@@ -876,6 +876,8 @@ struct usb_wireless_cap_descriptor { /* Ultra Wide Band */
	__u8  bReserved;
	__u8  bReserved;
} __attribute__((packed));
} __attribute__((packed));


#define USB_DT_USB_WIRELESS_CAP_SIZE	11

/* USB 2.0 Extension descriptor */
/* USB 2.0 Extension descriptor */
#define	USB_CAP_TYPE_EXT		2
#define	USB_CAP_TYPE_EXT		2


@@ -1068,6 +1070,7 @@ struct usb_ptm_cap_descriptor {
	__u8  bDevCapabilityType;
	__u8  bDevCapabilityType;
} __attribute__((packed));
} __attribute__((packed));


#define USB_DT_USB_PTM_ID_SIZE		3
/*
/*
 * The size of the descriptor for the Sublink Speed Attribute Count
 * The size of the descriptor for the Sublink Speed Attribute Count
 * (SSAC) specified in bmAttributes[4:0].
 * (SSAC) specified in bmAttributes[4:0].