Linux USB
 help / color / mirror / Atom feed
From: Cheng Yongkang <teel4res@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Mathias Nyman <mathias.nyman@intel.com>
Cc: Alan Stern <stern@rowland.harvard.edu>,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [BUG] usb: failed altsetting restore leaves xHCI ep with a NULL ring
Date: Sun, 15 Nov 2026 08:37:16 -0800	[thread overview]
Message-ID: <20261115163716.226763-1-teel4res@gmail.com> (raw)

Hi Greg, Mathias,

This one is from reading the code only; I could not reproduce it. It
needs SET_INTERFACE to fail and then the restore of the old altsetting
to fail too, on xHCI, so it is very unlikely in practice.

I know the kerneldoc of usb_set_interface() says that after a failure
the original altsetting may be disabled and drivers cannot rely on any
altsetting being in effect. My concern is only that a later usbfs
ioctl can still reach the HCD with that endpoint and oops.

The sequence, as I read it in next-20261113:

1. usb_set_interface() calls usb_disable_interface(dev, iface, false)
   and then usb_hcd_alloc_bandwidth() for the new altsetting. On xHCI,
   xhci_check_bandwidth() frees the rings of the old endpoints that
   are not reused. xhci_drop_endpoint() does not clear their hcpriv.

2. SET_INTERFACE fails, and the restore call
   usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting)
   fails too, for example on a ring allocation failure. Its result is
   ignored, and cur_altsetting still points at the old altsetting.

3. USBDEVFS_RESETEP on a bulk or interrupt endpoint of that old
   altsetting passes findintfep() and checkintf(). usb_reset_endpoint()
   still finds the endpoint, because usb_disable_endpoint() with
   reset_hardware=false keeps dev->ep_in/out[], and nothing checks
   ep->enabled.

4. xhci_endpoint_reset() sees a non-NULL hcpriv, passes its other
   checks, and reaches list_empty(&ep->ring->td_list) with a NULL
   ring.

Either side could avoid it: usb_set_interface() could check the
restore result and disable the interface with reset_hardware=true,
or xhci_endpoint_reset() could return early when ep->ring is NULL.
I have a draft of the first, but it is only tested on the normal
altsetting paths, not on this failure. Please tell me if you think it
is worth fixing and where.

Thanks,
Cheng Yongkang

                 reply	other threads:[~2026-11-15 16:37 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261115163716.226763-1-teel4res@gmail.com \
    --to=teel4res@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@intel.com \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox