Skip to content

Commit 2278446

Browse files
matnymangregkh
authored andcommitted
xhci: Fix USB3 NULL pointer dereference at logical disconnect.
Hub driver will try to disable a USB3 device twice at logical disconnect, racing with xhci_free_dev() callback from the first port disable. This can be triggered with "udisksctl power-off --block-device <disk>" or by writing "1" to the "remove" sysfs file for a USB3 device in 4.17-rc4. USB3 devices don't have a similar disabled link state as USB2 devices, and use a U3 suspended link state instead. In this state the port is still enabled and connected. hub_port_connect() first disconnects the device, then later it notices that device is still enabled (due to U3 states) it will try to disable the port again (set to U3). The xhci_free_dev() called during device disable is async, so checking for existing xhci->devs[i] when setting link state to U3 the second time was successful, even if device was being freed. The regression was caused by, and whole thing revealed by, Commit 44a182b ("xhci: Fix use-after-free in xhci_free_virt_device") which sets xhci->devs[i]->udev to NULL before xhci_virt_dev() returned. and causes a NULL pointer dereference the second time we try to set U3. Fix this by checking xhci->devs[i]->udev exists before setting link state. The original patch went to stable so this fix needs to be applied there as well. Fixes: 44a182b ("xhci: Fix use-after-free in xhci_free_virt_device") Cc: <[email protected]> Reported-by: Jordan Glover <[email protected]> Tested-by: Jordan Glover <[email protected]> Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 75bc37f commit 2278446

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

drivers/usb/host/xhci-hub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
354354

355355
slot_id = 0;
356356
for (i = 0; i < MAX_HC_SLOTS; i++) {
357-
if (!xhci->devs[i])
357+
if (!xhci->devs[i] || !xhci->devs[i]->udev)
358358
continue;
359359
speed = xhci->devs[i]->udev->speed;
360360
if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3))

0 commit comments

Comments
 (0)