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: Jack Pham <jackp@codeaurora.org>
This commit is contained in:
parent
28bf2d8b6b
commit
a4253a4598
1 changed files with 7 additions and 4 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue