Commit c9978130 authored by Mathias Nyman's avatar Mathias Nyman Committed by Zheng Yejian
Browse files

xhci: Fix null pointer dereference when host dies

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=6fac4b5cecb3928a0a81069aaa815a2edc8dd5a1



--------------------------------

commit a2bc47c4 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: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20230116142216.1141605-4-mathias.nyman@linux.intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarZheng Yejian <zhengyejian1@huawei.com>
parent bd13437d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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)