Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4253a45 authored by Jack Pham's avatar Jack Pham
Browse files

usb: xhci: Avoid accessing dangling virt_dev in xhci_stop_device



In xhci_stop_device() the virt_dev pointer is assigned from the
device slot prior to acquiring xhci->lock and disabling IRQs.
This is an opportunity for a TRB_DISABLE_SLOT command to have
completed (e.g. in case the device was disconnected, or the port
was disabled) which would have called xhci_free_virt_device()
and freed the slot's pointer in IRQ context. Then after the
lock is acquired virt_dev may now be pointing to freed memory
and results in a panic.

Avoid this by moving the assignment

	virt_dev = xhci->devs[slot_id];

and NULL pointer check to after the lock is taken to ensure that
we don't race against xhci IRQ handler.

Change-Id: I4ac23fbfd3def0ad93967316b62c0c0cd19ca33f
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 28bf2d8b
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -376,10 +376,6 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
	int i;

	ret = 0;
	virt_dev = xhci->devs[slot_id];
	if (!virt_dev)
		return -ENODEV;

	cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
	if (!cmd) {
		xhci_dbg(xhci, "Couldn't allocate command structure.\n");
@@ -387,6 +383,13 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
	}

	spin_lock_irqsave(&xhci->lock, flags);
	virt_dev = xhci->devs[slot_id];
	if (!virt_dev) {
		spin_unlock_irqrestore(&xhci->lock, flags);
		xhci_free_command(xhci, cmd);
		return -ENODEV;
	}

	for (i = LAST_EP_INDEX; i > 0; i--) {
		if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) {
			struct xhci_command *command;