From: Mathias Nyman mathias.nyman@linux.intel.com
stable inclusion from stable-v4.19.271 commit 6fac4b5cecb3928a0a81069aaa815a2edc8dd5a1 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IALLDG CVE: CVE-2023-52898
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
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 Conflicts: drivers/usb/host/xhci.c [Resolve conflicts due to previous bugfix] Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20230116142216.1141605-4-mathias.nyman@linux.intel... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zheng Yejian zhengyejian1@huawei.com --- drivers/usb/host/xhci.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 780d4354771e..1cb66cbe6487 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3774,6 +3774,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_virt_device *virt_dev; struct xhci_slot_ctx *slot_ctx; + unsigned long flags; int i, ret;
#ifndef CONFIG_USB_DEFAULT_PERSIST @@ -3804,7 +3805,11 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) } virt_dev->udev = NULL; xhci_disable_slot(xhci, udev->slot_id); + + spin_lock_irqsave(&xhci->lock, flags); 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)