patch "USB: core: fix check for duplicate endpoints" added to usb-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
USB: core: fix check for duplicate endpoints
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 3e4f8e21c4f27bcf30a48486b9dcc269512b79ff Mon Sep 17 00:00:00 2001
From: Johan Hovold <[email protected]>
Date: Thu, 19 Dec 2019 17:10:16 +0100
Subject: USB: core: fix check for duplicate endpoints
Amend the endpoint-descriptor sanity checks to detect all duplicate endpoint addresses in a configuration.
Commit 0a8fd1346254 ("USB: fix problems with duplicate endpoint addresses") added a check for duplicate endpoint addresses within a single alternate setting, but did not look for duplicate addresses in other interfaces.
The current check would also not detect all duplicate addresses when one endpoint is as a (bi-directional) control endpoint.
This specifically avoids overwriting the endpoint entries in struct usb_device when enabling a duplicate endpoint, something which could potentially lead to crashes or leaks, for example, when endpoints are later disabled.
--- drivers/usb/core/config.c | 70 ++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 12 deletions(-)
drivers/usb/core/config.c +58 -12
@@ -203,9 +203,58 @@ static const unsigned short super_speed_maxpacket_maxes[4] = { [USB_ENDPOINT_XFER_INT] = 1024, }; -static int usb_parse_endpoint (struct device *ddev,int cfgno,int inum, -int asnum,struct usb_host_interface *ifp,int num_ep, -unsigned char *buffer,int size) +static bool endpoint_is_duplicate (struct usb_endpoint_descriptor *e1, +struct usb_endpoint_descriptor *e2) +{ +if (e1->bEndpointAddress == e2->bEndpointAddress) +return true; + +if (usb_endpoint_xfer_control (e1) ||usb_endpoint_xfer_control (e2)) { +if (usb_endpoint_num (e1) ==usb_endpoint_num (e2)) +return true; + } + +return false; +} + +/* +* Check for duplicate endpoint addresses in other interfaces and in the +* altsetting currently being parsed. +*/ +static bool config_endpoint_is_duplicate (struct usb_host_config *config, +int inum,int asnum,struct usb_endpoint_descriptor *d) +{ +struct usb_endpoint_descriptor *epd; +struct usb_interface_cache *intfc; +struct usb_host_interface *alt; +int i, j, k; + +for (i =0 ; i < config->desc.bNumInterfaces; ++i) { + intfc = config->intf_cache[i]; + +for (j =0 ; j < intfc->num_altsetting; ++j) { + alt = &intfc->altsetting[j]; + +if (alt->desc.bInterfaceNumber == inum && + alt->desc.bAlternateSetting != asnum) +continue ; + +for (k =0 ; k < alt->desc.bNumEndpoints; ++k) { + epd = &alt->endpoint[k].desc; + +if (endpoint_is_duplicate (epd, d)) +return true; + } + } + } + +return false; +} + +static int usb_parse_endpoint (struct device *ddev,int cfgno, +struct usb_host_config *config,int inum,int asnum, +struct usb_host_interface *ifp,int num_ep, +unsigned char *buffer,int size) {unsigned char *buffer0 = buffer;struct usb_endpoint_descriptor *d;
@@ -242,13 +291,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, goto skip_to_next_endpoint_or_interface_descriptor;/* Check for duplicate endpoint addresses */ -for (i =0 ; i < ifp->desc.bNumEndpoints; ++i) { -if (ifp->endpoint[i].desc.bEndpointAddress == - d->bEndpointAddress) { -dev_warn (ddev,"config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n" , - cfgno, inum, asnum, d->bEndpointAddress); - goto skip_to_next_endpoint_or_interface_descriptor; - } +if (config_endpoint_is_duplicate (config, inum, asnum, d)) { +dev_warn (ddev,"config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n" , + cfgno, inum, asnum, d->bEndpointAddress); + goto skip_to_next_endpoint_or_interface_descriptor; } endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
@@ -522,8 +568,8 @@ static int usb_parse_interface(struct device *ddev, int cfgno,if (((struct usb_descriptor_header *) buffer)->bDescriptorType ==USB_DT_INTERFACE )break ; - retval =usb_parse_endpoint (ddev, cfgno, inum, asnum, alt, - num_ep, buffer, size); + retval =usb_parse_endpoint (ddev, cfgno, config, inum, asnum, + alt, num_ep, buffer, size);if (retval <0 )return retval; ++n;
Signature · 1 line
2.24.1