mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	USB: core: Add type-specific length check of BOS descriptors
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> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									1d5a31582e
								
							
						
					
					
						commit
						81cf4a4536
					
				
					 2 changed files with 27 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
int usb_get_bos_descriptor(struct usb_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct device *ddev = &dev->dev;
 | 
			
		||||
	struct usb_bos_descriptor *bos;
 | 
			
		||||
	struct usb_dev_cap_header *cap;
 | 
			
		||||
	struct usb_ssp_cap_descriptor *ssp_cap;
 | 
			
		||||
	unsigned char *buffer;
 | 
			
		||||
	int length, total_len, num, i;
 | 
			
		||||
	int length, total_len, num, i, ssac;
 | 
			
		||||
	__u8 cap_type;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
			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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -973,7 +990,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -986,8 +1003,11 @@ int usb_get_bos_descriptor(struct usb_device *dev)
 | 
			
		|||
				(struct usb_ss_cap_descriptor *)buffer;
 | 
			
		||||
			break;
 | 
			
		||||
		case USB_SSP_CAP_TYPE:
 | 
			
		||||
			dev->bos->ssp_cap =
 | 
			
		||||
				(struct usb_ssp_cap_descriptor *)buffer;
 | 
			
		||||
			ssp_cap = (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;
 | 
			
		||||
		case CONTAINER_ID_TYPE:
 | 
			
		||||
			dev->bos->ss_id =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -880,6 +880,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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1072,6 +1074,7 @@ struct usb_ptm_cap_descriptor {
 | 
			
		|||
	__u8  bDevCapabilityType;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
#define USB_DT_USB_PTM_ID_SIZE		3
 | 
			
		||||
/*
 | 
			
		||||
 * The size of the descriptor for the Sublink Speed Attribute Count
 | 
			
		||||
 * (SSAC) specified in bmAttributes[4:0].
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue