drivers/usb/core/message.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
In usb_enable_endpoint(), non-zero control endpoints (where
usb_endpoint_xfer_control(&ep->desc) is true) populate both
dev->ep_in[epnum] and dev->ep_out[epnum] with the same
struct usb_host_endpoint pointer.
However, usb_disable_endpoint() only clears either dev->ep_out[epnum]
or dev->ep_in[epnum] depending on the direction bit of epaddr when
reset_hardware is set, leaving the opposite direction's array slot
pointing to the disabled/freed endpoint.
Clear both dev->ep_out[epnum] and dev->ep_in[epnum] when disabling a
non-ep0 control endpoint with reset_hardware set, and update the
function kerneldoc accordingly.
Tested in QEMU against Linux 7.3.0-rc3 using dummy_hcd and raw-gadget to
enumerate a USB device with a non-zero control endpoint (bEndpointAddress
0x01, bmAttributes USB_ENDPOINT_XFER_CONTROL), verifying that both
dev->ep_in[1] and dev->ep_out[1] are cleared when the interface is
disabled.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
---
Changes in v2:
- Dropped all changes in the other files (config.c, hub.c, port.c,
devio.c, sysfs.c, and ledtrig-usbport.c) per Alan Stern and Greg
Kroah-Hartman, keeping only the usb_disable_endpoint() fix in
drivers/usb/core/message.c.
- Updated the usb_disable_endpoint() kerneldoc comment and commit
description per Alan Stern.
drivers/usb/core/message.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 75e2bfd744a9..0cd6dd2b6334 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1337,7 +1337,8 @@ static void remove_intf_ep_devs(struct usb_interface *intf)
*
* Disables the endpoint for URB submission and nukes all pending URBs.
* If @reset_hardware is set then also deallocates hcd/hardware state
- * for the endpoint.
+ * for the endpoint (clearing both ep_in and ep_out pointers for
+ * bidirectional non-ep0 control endpoints).
*/
void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
bool reset_hardware)
@@ -1358,6 +1359,11 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
dev->ep_in[epnum] = NULL;
}
if (ep) {
+ if (reset_hardware && epnum != 0 &&
+ usb_endpoint_xfer_control(&ep->desc)) {
+ dev->ep_out[epnum] = NULL;
+ dev->ep_in[epnum] = NULL;
+ }
ep->enabled = 0;
usb_hcd_flush_endpoint(dev, ep);
if (reset_hardware)
--
2.47.3
On Sun, Sep 20, 2026 at 11:17:02PM +0000, Hui Peng wrote:
> In usb_enable_endpoint(), non-zero control endpoints (where
> usb_endpoint_xfer_control(&ep->desc) is true) populate both
> dev->ep_in[epnum] and dev->ep_out[epnum] with the same
> struct usb_host_endpoint pointer.
>
> However, usb_disable_endpoint() only clears either dev->ep_out[epnum]
> or dev->ep_in[epnum] depending on the direction bit of epaddr when
> reset_hardware is set, leaving the opposite direction's array slot
> pointing to the disabled/freed endpoint.
>
> Clear both dev->ep_out[epnum] and dev->ep_in[epnum] when disabling a
> non-ep0 control endpoint with reset_hardware set, and update the
> function kerneldoc accordingly.
>
> Tested in QEMU against Linux 7.3.0-rc3 using dummy_hcd and raw-gadget to
> enumerate a USB device with a non-zero control endpoint (bEndpointAddress
> 0x01, bmAttributes USB_ENDPOINT_XFER_CONTROL), verifying that both
> dev->ep_in[1] and dev->ep_out[1] are cleared when the interface is
> disabled.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Hui Peng <benquike@gmail.com>
> ---
> Changes in v2:
> - Dropped all changes in the other files (config.c, hub.c, port.c,
> devio.c, sysfs.c, and ledtrig-usbport.c) per Alan Stern and Greg
> Kroah-Hartman, keeping only the usb_disable_endpoint() fix in
> drivers/usb/core/message.c.
> - Updated the usb_disable_endpoint() kerneldoc comment and commit
> description per Alan Stern.
Acked-by: Alan Stern <stern@rowland.harvard.edu>
You might consider looking through other parts of the code to see if
they need similar attention. Historically we haven't been very good
about supporting control endpoints other than ep0.
Alan Stern
> drivers/usb/core/message.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
> index 75e2bfd744a9..0cd6dd2b6334 100644
> --- a/drivers/usb/core/message.c
> +++ b/drivers/usb/core/message.c
> @@ -1337,7 +1337,8 @@ static void remove_intf_ep_devs(struct usb_interface *intf)
> *
> * Disables the endpoint for URB submission and nukes all pending URBs.
> * If @reset_hardware is set then also deallocates hcd/hardware state
> - * for the endpoint.
> + * for the endpoint (clearing both ep_in and ep_out pointers for
> + * bidirectional non-ep0 control endpoints).
> */
> void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
> bool reset_hardware)
> @@ -1358,6 +1359,11 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
> dev->ep_in[epnum] = NULL;
> }
> if (ep) {
> + if (reset_hardware && epnum != 0 &&
> + usb_endpoint_xfer_control(&ep->desc)) {
> + dev->ep_out[epnum] = NULL;
> + dev->ep_in[epnum] = NULL;
> + }
> ep->enabled = 0;
> usb_hcd_flush_endpoint(dev, ep);
> if (reset_hardware)
> --
> 2.47.3
On Sun, Sep 20, 2026 at 8:21 PM Alan Stern <stern@rowland.harvard.edu> wrote: > > Acked-by: Alan Stern <stern@rowland.harvard.edu> > > You might consider looking through other parts of the code to see if > they need similar attention. Historically we haven't been very good > about supporting control endpoints other than ep0. > > Alan Stern Thank you for the review and Acked-by, Alan. We will audit the rest of the USB core and host controller paths for non-ep0 control endpoint handling, and if we find any additional issues, we will report and submit them in separate patches. Best regards, Hui Peng
© 2016 - 2026 Red Hat, Inc.