summaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorAlan Stern2008-10-21 21:28:46 +0200
committerGreg Kroah-Hartman2008-10-29 22:54:40 +0100
commitcde217a556ec552d28ac9e136c5a94684a69ae94 (patch)
tree6b8368511301e513c6de8a40dffa357c1064b20e /drivers/usb/core/hub.c
parentMerge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/... (diff)
downloadkernel-qcow2-linux-cde217a556ec552d28ac9e136c5a94684a69ae94.tar.gz
kernel-qcow2-linux-cde217a556ec552d28ac9e136c5a94684a69ae94.tar.xz
kernel-qcow2-linux-cde217a556ec552d28ac9e136c5a94684a69ae94.zip
USB: fix crash when URBs are unlinked after the device is gone
This patch (as1151) protects usbcore against drivers that try to unlink an URB after the URB's device or bus have been removed. The core does not currently check for this, and certain drivers can cause a crash if they are running while an HCD is unloaded. Certainly it would be best to fix the guilty drivers. But a little defensive programming doesn't hurt, especially since it appears that quite a few drivers need to be fixed. The patch prevents the problem by grabbing a reference to the device while an unlink is in progress and using a new spinlock to synchronize unlinks with device removal. (There's no need to acquire a reference to the bus as well, since the device structure itself keeps a reference to the bus.) In addition, the kerneldoc is updated to indicate that URBs should not be unlinked after the disconnect method returns. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 9b3f16bd12cb..37ff8aed256d 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1429,6 +1429,7 @@ void usb_disconnect(struct usb_device **pdev)
*/
dev_dbg (&udev->dev, "unregistering device\n");
usb_disable_device(udev, 0);
+ usb_hcd_synchronize_unlinks(udev);
usb_unlock_device(udev);