xhci: Fix null pointer dereference when host dies

commit a2bc47c43e70cf904b1af49f76d572326c08bca7 upstream.

Make sure xhci_free_dev() and xhci_kill_endpoint_urbs() do not race
and cause null pointer dereference when host suddenly dies.

Usb core may call xhci_free_dev() which frees the xhci->devs[slot_id]
virt device at the same time that xhci_kill_endpoint_urbs() tries to
loop through all the device's endpoints, checking if there are any
cancelled urbs left to give back.

hold the xhci spinlock while freeing the virt device

Cc: stable@vger.kernel.org
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20230116142216.1141605-4-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Mathias Nyman 2023-01-16 16:22:12 +02:00 committed by Greg Kroah-Hartman
parent 9891e5c73c
commit 133b902378

View File

@ -3909,6 +3909,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_virt_device *virt_dev; struct xhci_virt_device *virt_dev;
struct xhci_slot_ctx *slot_ctx; struct xhci_slot_ctx *slot_ctx;
unsigned long flags;
int i, ret; int i, ret;
/* /*
@ -3937,7 +3938,11 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
} }
virt_dev->udev = NULL; virt_dev->udev = NULL;
xhci_disable_slot(xhci, udev->slot_id); xhci_disable_slot(xhci, udev->slot_id);
spin_lock_irqsave(&xhci->lock, flags);
xhci_free_virt_device(xhci, udev->slot_id); xhci_free_virt_device(xhci, udev->slot_id);
spin_unlock_irqrestore(&xhci->lock, flags);
} }
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)