diff options
author | Mathias Nyman <mathias.nyman@linux.intel.com> | 2016-03-29 12:47:09 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-03-31 06:57:58 +0200 |
commit | 59b9023c356c54e5f468029fa504461d04c0f02b (patch) | |
tree | 95839eb474a8ed6be47c853ea217f0035e79d613 /drivers/usb | |
parent | USB: usbip: fix potential out-of-bounds write (diff) | |
download | linux-59b9023c356c54e5f468029fa504461d04c0f02b.tar.xz linux-59b9023c356c54e5f468029fa504461d04c0f02b.zip |
usb: fix regression in SuperSpeed endpoint descriptor parsing
commit b37d83a6a414 ("usb: Parse the new USB 3.1 SuperSpeedPlus Isoc
endpoint companion descriptor") caused a regression in 4.6-rc1 and fails
to parse SuperSpeed endpoint companion descriptors.
The new SuperSpeedPlus Isoc endpoint companion parsing code incorrectly
decreased the the remaining buffer size before comparing the size with the
expected length of the descriptor.
This lead to possible failure in reading the SuperSpeed endpoint companion
descriptor of the last endpoint, displaying a message like:
"No SuperSpeed endpoint companion for config 1 interface 0 altsetting 0
ep 129: using minimum values"
Fix it by decreasing the size after comparing it.
Also finish all the SS endpoint companion parsing before calling SSP isoc
endpoint parsing function.
Fixes: b37d83a6a414
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/config.c | 16 |
1 files changed, 7 insertions, 9 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 5eb1a87228b4..31ccdccd7a04 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -75,8 +75,6 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, * be the first thing immediately following the endpoint descriptor. */ desc = (struct usb_ss_ep_comp_descriptor *) buffer; - buffer += desc->bLength; - size -= desc->bLength; if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP || size < USB_DT_SS_EP_COMP_SIZE) { @@ -100,7 +98,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, ep->desc.wMaxPacketSize; return; } - + buffer += desc->bLength; + size -= desc->bLength; memcpy(&ep->ss_ep_comp, desc, USB_DT_SS_EP_COMP_SIZE); /* Check the various values */ @@ -146,12 +145,6 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, ep->ss_ep_comp.bmAttributes = 2; } - /* Parse a possible SuperSpeedPlus isoc ep companion descriptor */ - if (usb_endpoint_xfer_isoc(&ep->desc) && - USB_SS_SSP_ISOC_COMP(desc->bmAttributes)) - usb_parse_ssp_isoc_endpoint_companion(ddev, cfgno, inum, asnum, - ep, buffer, size); - if (usb_endpoint_xfer_isoc(&ep->desc)) max_tx = (desc->bMaxBurst + 1) * (USB_SS_MULT(desc->bmAttributes)) * @@ -171,6 +164,11 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, max_tx); ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx); } + /* Parse a possible SuperSpeedPlus isoc ep companion descriptor */ + if (usb_endpoint_xfer_isoc(&ep->desc) && + USB_SS_SSP_ISOC_COMP(desc->bmAttributes)) + usb_parse_ssp_isoc_endpoint_companion(ddev, cfgno, inum, asnum, + ep, buffer, size); } static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, |