Skip to content

Commit cb53c51

Browse files
matnymangregkh
authored andcommitted
xhci: Fix NULL pointer dereference at endpoint zero reset.
Usb core will reset the default control endpoint "ep0" before resetting a device. if the endpoint has a valid pointer back to the usb device then the xhci driver reset callback will try to clear the toggle for the endpoint. ep0 didn't use to have this pointer set as ep0 was always allocated by default together with a xhci slot for the usb device. Other endpoints got their usb device pointer set in xhci_add_endpoint() This changed with commit ef513be ("usb: xhci: Add Clear_TT_Buffer") which sets the pointer for any endpoint on a FS/LS device behind a HS hub that halts, including ep0. If xHC controller needs to be reset at resume, then all the xhci slots will be lost. Slots will be reenabled and reallocated at device reset, but unlike other endpoints the ep0 is reset before device reset, while the xhci slot may still be invalid, causing NULL pointer dereference. Fix it by checking that the endpoint has both a usb device pointer and valid xhci slot before trying to clear the toggle. This issue was not seen earlier as ep0 didn't use to have a valid usb device pointer, and other endpoints were only reset after device reset when xhci slots were properly reenabled. Reported-by: Bob Gleitsmann <[email protected]> Reported-by: Enric Balletbo Serra <[email protected]> Fixes: ef513be ("usb: xhci: Add Clear_TT_Buffer") Signed-off-by: Mathias Nyman <[email protected]> Tested-by: Enric Balletbo i Serra <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 783bda5 commit cb53c51

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

drivers/usb/host/xhci.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3089,8 +3089,18 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
30893089
return;
30903090
udev = (struct usb_device *) host_ep->hcpriv;
30913091
vdev = xhci->devs[udev->slot_id];
3092+
3093+
/*
3094+
* vdev may be lost due to xHC restore error and re-initialization
3095+
* during S3/S4 resume. A new vdev will be allocated later by
3096+
* xhci_discover_or_reset_device()
3097+
*/
3098+
if (!udev->slot_id || !vdev)
3099+
return;
30923100
ep_index = xhci_get_endpoint_index(&host_ep->desc);
30933101
ep = &vdev->eps[ep_index];
3102+
if (!ep)
3103+
return;
30943104

30953105
/* Bail out if toggle is already being cleared by a endpoint reset */
30963106
if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {

0 commit comments

Comments
 (0)