Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Masakazu Mokuno and committed by
Greg Kroah-Hartman
81cf4a45 1d5a3158

+27 -4
+24 -4
drivers/usb/core/config.c
··· 905 905 } 906 906 } 907 907 908 + static const __u8 bos_desc_len[256] = { 909 + [USB_CAP_TYPE_WIRELESS_USB] = USB_DT_USB_WIRELESS_CAP_SIZE, 910 + [USB_CAP_TYPE_EXT] = USB_DT_USB_EXT_CAP_SIZE, 911 + [USB_SS_CAP_TYPE] = USB_DT_USB_SS_CAP_SIZE, 912 + [USB_SSP_CAP_TYPE] = USB_DT_USB_SSP_CAP_SIZE(1), 913 + [CONTAINER_ID_TYPE] = USB_DT_USB_SS_CONTN_ID_SIZE, 914 + [USB_PTM_CAP_TYPE] = USB_DT_USB_PTM_ID_SIZE, 915 + }; 916 + 908 917 /* Get BOS descriptor set */ 909 918 int usb_get_bos_descriptor(struct usb_device *dev) 910 919 { 911 920 struct device *ddev = &dev->dev; 912 921 struct usb_bos_descriptor *bos; 913 922 struct usb_dev_cap_header *cap; 923 + struct usb_ssp_cap_descriptor *ssp_cap; 914 924 unsigned char *buffer; 915 - int length, total_len, num, i; 925 + int length, total_len, num, i, ssac; 926 + __u8 cap_type; 916 927 int ret; 917 928 918 929 bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL); ··· 976 965 dev->bos->desc->bNumDeviceCaps = i; 977 966 break; 978 967 } 968 + cap_type = cap->bDevCapabilityType; 979 969 length = cap->bLength; 970 + if (bos_desc_len[cap_type] && length < bos_desc_len[cap_type]) { 971 + dev->bos->desc->bNumDeviceCaps = i; 972 + break; 973 + } 974 + 980 975 total_len -= length; 981 976 982 977 if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { ··· 990 973 continue; 991 974 } 992 975 993 - switch (cap->bDevCapabilityType) { 976 + switch (cap_type) { 994 977 case USB_CAP_TYPE_WIRELESS_USB: 995 978 /* Wireless USB cap descriptor is handled by wusb */ 996 979 break; ··· 1003 986 (struct usb_ss_cap_descriptor *)buffer; 1004 987 break; 1005 988 case USB_SSP_CAP_TYPE: 1006 - dev->bos->ssp_cap = 1007 - (struct usb_ssp_cap_descriptor *)buffer; 989 + ssp_cap = (struct usb_ssp_cap_descriptor *)buffer; 990 + ssac = (le32_to_cpu(ssp_cap->bmAttributes) & 991 + USB_SSP_SUBLINK_SPEED_ATTRIBS) + 1; 992 + if (length >= USB_DT_USB_SSP_CAP_SIZE(ssac)) 993 + dev->bos->ssp_cap = ssp_cap; 1008 994 break; 1009 995 case CONTAINER_ID_TYPE: 1010 996 dev->bos->ss_id =
+3
include/uapi/linux/usb/ch9.h
··· 880 880 __u8 bReserved; 881 881 } __attribute__((packed)); 882 882 883 + #define USB_DT_USB_WIRELESS_CAP_SIZE 11 884 + 883 885 /* USB 2.0 Extension descriptor */ 884 886 #define USB_CAP_TYPE_EXT 2 885 887 ··· 1074 1072 __u8 bDevCapabilityType; 1075 1073 } __attribute__((packed)); 1076 1074 1075 + #define USB_DT_USB_PTM_ID_SIZE 3 1077 1076 /* 1078 1077 * The size of the descriptor for the Sublink Speed Attribute Count 1079 1078 * (SSAC) specified in bmAttributes[4:0].