summaryrefslogtreecommitdiff
path: root/drivers/net/usb/usbnet.c
diff options
context:
space:
mode:
authorClark Williams <williams@redhat.com>2012-04-04 10:52:26 -0500
committerClark Williams <williams@redhat.com>2012-04-04 10:52:26 -0500
commit2d93eaf2d4ace5853a74a4b0596f601aa62cb840 (patch)
treeb0a2e2083c1749c4e3b8ae23db7bb13a7ca9aafe /drivers/net/usb/usbnet.c
parent003133585fc61d7bd36d3a097d7fde62e64a9550 (diff)
parent23d8c3f8f494c8516c9b4c05529e118e6a485956 (diff)
Merge commit 'v3.2.14' into rt-3.2.14-rt23v3.2.14-rt23
Diffstat (limited to 'drivers/net/usb/usbnet.c')
-rw-r--r--drivers/net/usb/usbnet.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 81b96e303757..750e33099cc1 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -589,6 +589,14 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
entry = (struct skb_data *) skb->cb;
urb = entry->urb;
+ /*
+ * Get reference count of the URB to avoid it to be
+ * freed during usb_unlink_urb, which may trigger
+ * use-after-free problem inside usb_unlink_urb since
+ * usb_unlink_urb is always racing with .complete
+ * handler(include defer_bh).
+ */
+ usb_get_urb(urb);
spin_unlock_irqrestore(&q->lock, flags);
// during some PM-driven resume scenarios,
// these (async) unlinks complete immediately
@@ -597,6 +605,7 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
netdev_dbg(dev->net, "unlink urb err, %d\n", retval);
else
count++;
+ usb_put_urb(urb);
spin_lock_irqsave(&q->lock, flags);
}
spin_unlock_irqrestore (&q->lock, flags);
@@ -1028,7 +1037,6 @@ static void tx_complete (struct urb *urb)
}
usb_autopm_put_interface_async(dev->intf);
- urb->dev = NULL;
entry->state = tx_done;
defer_bh(dev, skb, &dev->txq);
}