aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2015-01-30 12:58:26 -0500
committerGreg Kroah-Hartman <greg@kroah.com>2015-01-31 12:05:06 -0500
commitc99197902da284b4b723451c1471c45b18537cde (patch)
treeff9d749b80d391ccc7b2dcd769c475facdeb9897 /drivers/usb/core
parentcefa9a31a5f0856b81d53030815485fcb1fe8aab (diff)
USB: fix use-after-free bug in usb_hcd_unlink_urb()
The usb_hcd_unlink_urb() routine in hcd.c contains two possible use-after-free errors. The dev_dbg() statement at the end of the routine dereferences urb and urb->dev even though both structures may have been deallocated. This patch fixes the problem by storing urb->dev in a local variable (avoiding the dereference of urb) and moving the dev_dbg() up before the usb_put_dev() call. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Reported-by: Joe Lawrence <joe.lawrence@stratus.com> Tested-by: Joe Lawrence <joe.lawrence@stratus.com> CC: <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hcd.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 11cee55ae397..45a915ccd71c 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1618,6 +1618,7 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status)
1618int usb_hcd_unlink_urb (struct urb *urb, int status) 1618int usb_hcd_unlink_urb (struct urb *urb, int status)
1619{ 1619{
1620 struct usb_hcd *hcd; 1620 struct usb_hcd *hcd;
1621 struct usb_device *udev = urb->dev;
1621 int retval = -EIDRM; 1622 int retval = -EIDRM;
1622 unsigned long flags; 1623 unsigned long flags;
1623 1624
@@ -1629,20 +1630,19 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
1629 spin_lock_irqsave(&hcd_urb_unlink_lock, flags); 1630 spin_lock_irqsave(&hcd_urb_unlink_lock, flags);
1630 if (atomic_read(&urb->use_count) > 0) { 1631 if (atomic_read(&urb->use_count) > 0) {
1631 retval = 0; 1632 retval = 0;
1632 usb_get_dev(urb->dev); 1633 usb_get_dev(udev);
1633 } 1634 }
1634 spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags); 1635 spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags);
1635 if (retval == 0) { 1636 if (retval == 0) {
1636 hcd = bus_to_hcd(urb->dev->bus); 1637 hcd = bus_to_hcd(urb->dev->bus);
1637 retval = unlink1(hcd, urb, status); 1638 retval = unlink1(hcd, urb, status);
1638 usb_put_dev(urb->dev); 1639 if (retval == 0)
1640 retval = -EINPROGRESS;
1641 else if (retval != -EIDRM && retval != -EBUSY)
1642 dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n",
1643 urb, retval);
1644 usb_put_dev(udev);
1639 } 1645 }
1640
1641 if (retval == 0)
1642 retval = -EINPROGRESS;
1643 else if (retval != -EIDRM && retval != -EBUSY)
1644 dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n",
1645 urb, retval);
1646 return retval; 1646 return retval;
1647} 1647}
1648 1648