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

USB: Fix parsing of SuperSpeed Endpoint Companion descriptor.

usb_parse_ss_endpoint_companion() was supposed to allocate a structure to
hold the SuperSpeed Endpoint Companion descriptor, and either copy the
values the device returned, or fill in default values if the device
descriptor did not include the companion descriptor.

However, the previous code would miss the last endpoint in a configuration
with no descriptors after it. Make usb_parse_endpoint() allocate the SS
endpoint companion descriptor and fill it with default values, even if
we've run out of buffer space in this configuration descriptor.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Sarah Sharp and committed by
Greg Kroah-Hartman
9f8e4438 b7d6d998

+27 -21
+27 -21
drivers/usb/core/config.c
··· 80 80 int max_tx; 81 81 int i; 82 82 83 - /* Allocate space for the SS endpoint companion descriptor */ 84 - ep->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp), 85 - GFP_KERNEL); 86 - if (!ep->ss_ep_comp) 87 - return -ENOMEM; 88 83 desc = (struct usb_ss_ep_comp_descriptor *) buffer; 89 84 if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) { 90 85 dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " 91 86 " interface %d altsetting %d ep %d: " 92 87 "using minimum values\n", 93 88 cfgno, inum, asnum, ep->desc.bEndpointAddress); 94 - ep->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE; 95 - ep->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; 96 - ep->ss_ep_comp->desc.bMaxBurst = 0; 97 - /* 98 - * Leave bmAttributes as zero, which will mean no streams for 99 - * bulk, and isoc won't support multiple bursts of packets. 100 - * With bursts of only one packet, and a Mult of 1, the max 101 - * amount of data moved per endpoint service interval is one 102 - * packet. 103 - */ 104 - if (usb_endpoint_xfer_isoc(&ep->desc) || 105 - usb_endpoint_xfer_int(&ep->desc)) 106 - ep->ss_ep_comp->desc.wBytesPerInterval = 107 - ep->desc.wMaxPacketSize; 108 89 /* 109 90 * The next descriptor is for an Endpoint or Interface, 110 91 * no extra descriptors to copy into the companion structure, 111 92 * and we didn't eat up any of the buffer. 112 93 */ 113 - retval = 0; 114 - goto valid; 94 + return 0; 115 95 } 116 96 memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE); 117 97 desc = &ep->ss_ep_comp->desc; ··· 300 320 buffer += i; 301 321 size -= i; 302 322 323 + /* Allocate space for the SS endpoint companion descriptor */ 324 + endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp), 325 + GFP_KERNEL); 326 + if (!endpoint->ss_ep_comp) 327 + return -ENOMEM; 328 + 329 + /* Fill in some default values (may be overwritten later) */ 330 + endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE; 331 + endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; 332 + endpoint->ss_ep_comp->desc.bMaxBurst = 0; 333 + /* 334 + * Leave bmAttributes as zero, which will mean no streams for 335 + * bulk, and isoc won't support multiple bursts of packets. 336 + * With bursts of only one packet, and a Mult of 1, the max 337 + * amount of data moved per endpoint service interval is one 338 + * packet. 339 + */ 340 + if (usb_endpoint_xfer_isoc(&endpoint->desc) || 341 + usb_endpoint_xfer_int(&endpoint->desc)) 342 + endpoint->ss_ep_comp->desc.wBytesPerInterval = 343 + endpoint->desc.wMaxPacketSize; 344 + 303 345 if (size > 0) { 304 346 retval = usb_parse_ss_endpoint_companion(ddev, cfgno, 305 347 inum, asnum, endpoint, num_ep, buffer, ··· 331 329 retval = buffer - buffer0; 332 330 } 333 331 } else { 332 + dev_warn(ddev, "config %d interface %d altsetting %d " 333 + "endpoint 0x%X has no " 334 + "SuperSpeed companion descriptor\n", 335 + cfgno, inum, asnum, d->bEndpointAddress); 334 336 retval = buffer - buffer0; 335 337 } 336 338 } else {