LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org, jejb@kernel.org
Cc: Justin Forbes <jmforbes@linuxtx.org>,
	Zwane Mwaikambo <zwane@arm.linux.org.uk>,
	"Theodore Ts'o" <tytso@mit.edu>,
	Randy Dunlap <rdunlap@xenotime.net>,
	Dave Jones <davej@redhat.com>,
	Chuck Wolber <chuckw@quantumlinux.com>,
	Chris Wedgwood <reviews@ml.cw.f00f.org>,
	Michael Krufky <mkrufky@linuxtv.org>,
	Chuck Ebbert <cebbert@redhat.com>,
	Domenico Andreoli <cavokz@gmail.com>, Willy Tarreau <w@1wt.eu>,
	Rodrigo Rubira Branco <rbranco@la.checkpoint.com>,
	Jake Edge <jake@lwn.net>, Eugene Teo <eteo@redhat.com>,
	torvalds@linux-foundation.org, akpm@linux-foundation.org,
	alan@lxorguk.ukuu.org.uk, Alan Stern <stern@rowland.harvard.edu>
Subject: [patch 06/57] USB: fix crash when URBs are unlinked after the device is gone
Date: Tue, 4 Nov 2008 15:31:09 -0800	[thread overview]
Message-ID: <20081104233109.GG659@suse.de> (raw)
In-Reply-To: <20081104233028.GA659@suse.de>

[-- Attachment #1: usb-fix-crash-when-urbs-are-unlinked-after-the-device-is-gone.patch --]
[-- Type: text/plain, Size: 5889 bytes --]

2.6.27-stable review patch.  If anyone has any objections, please let us know.

------------------
From: Alan Stern <stern@rowland.harvard.edu>

commit cde217a556ec552d28ac9e136c5a94684a69ae94 upstream

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/usb/core/hcd.c |   35 ++++++++++++++++++++++++++++++++---
 drivers/usb/core/hcd.h |    1 +
 drivers/usb/core/hub.c |    1 +
 drivers/usb/core/urb.c |   15 +++++++++++++++
 4 files changed, 49 insertions(+), 3 deletions(-)

--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -106,6 +106,9 @@ static DEFINE_SPINLOCK(hcd_root_hub_lock
 /* used when updating an endpoint's URB list */
 static DEFINE_SPINLOCK(hcd_urb_list_lock);
 
+/* used to protect against unlinking URBs after the device is gone */
+static DEFINE_SPINLOCK(hcd_urb_unlink_lock);
+
 /* wait queue for synchronous unlinks */
 DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
 
@@ -1377,10 +1380,25 @@ static int unlink1(struct usb_hcd *hcd, 
 int usb_hcd_unlink_urb (struct urb *urb, int status)
 {
 	struct usb_hcd		*hcd;
-	int			retval;
+	int			retval = -EIDRM;
+	unsigned long		flags;
 
-	hcd = bus_to_hcd(urb->dev->bus);
-	retval = unlink1(hcd, urb, status);
+	/* Prevent the device and bus from going away while
+	 * the unlink is carried out.  If they are already gone
+	 * then urb->use_count must be 0, since disconnected
+	 * devices can't have any active URBs.
+	 */
+	spin_lock_irqsave(&hcd_urb_unlink_lock, flags);
+	if (atomic_read(&urb->use_count) > 0) {
+		retval = 0;
+		usb_get_dev(urb->dev);
+	}
+	spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags);
+	if (retval == 0) {
+		hcd = bus_to_hcd(urb->dev->bus);
+		retval = unlink1(hcd, urb, status);
+		usb_put_dev(urb->dev);
+	}
 
 	if (retval == 0)
 		retval = -EINPROGRESS;
@@ -1529,6 +1547,17 @@ void usb_hcd_disable_endpoint(struct usb
 		hcd->driver->endpoint_disable(hcd, ep);
 }
 
+/* Protect against drivers that try to unlink URBs after the device
+ * is gone, by waiting until all unlinks for @udev are finished.
+ * Since we don't currently track URBs by device, simply wait until
+ * nothing is running in the locked region of usb_hcd_unlink_urb().
+ */
+void usb_hcd_synchronize_unlinks(struct usb_device *udev)
+{
+	spin_lock_irq(&hcd_urb_unlink_lock);
+	spin_unlock_irq(&hcd_urb_unlink_lock);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* called in any context */
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -232,6 +232,7 @@ extern void usb_hcd_flush_endpoint(struc
 		struct usb_host_endpoint *ep);
 extern void usb_hcd_disable_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
+extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
 extern int usb_hcd_get_frame_number(struct usb_device *udev);
 
 extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1349,6 +1349,7 @@ void usb_disconnect(struct usb_device **
 	 */
 	dev_dbg (&udev->dev, "unregistering device\n");
 	usb_disable_device(udev, 0);
+	usb_hcd_synchronize_unlinks(udev);
 
 	usb_unlock_device(udev);
 
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -465,6 +465,12 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
  * indicating that the request has been canceled (rather than any other
  * code).
  *
+ * Drivers should not call this routine or related routines, such as
+ * usb_kill_urb() or usb_unlink_anchored_urbs(), after their disconnect
+ * method has returned.  The disconnect function should synchronize with
+ * a driver's I/O routines to insure that all URB-related activity has
+ * completed before it returns.
+ *
  * This request is always asynchronous.  Success is indicated by
  * returning -EINPROGRESS, at which time the URB will probably not yet
  * have been given back to the device driver.  When it is eventually
@@ -541,6 +547,9 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb);
  * This routine may not be used in an interrupt context (such as a bottom
  * half or a completion handler), or when holding a spinlock, or in other
  * situations where the caller can't schedule().
+ *
+ * This routine should not be called by a driver after its disconnect
+ * method has returned.
  */
 void usb_kill_urb(struct urb *urb)
 {
@@ -568,6 +577,9 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
  *
  * this allows all outstanding URBs to be killed starting
  * from the back of the queue
+ *
+ * This routine should not be called by a driver after its disconnect
+ * method has returned.
  */
 void usb_kill_anchored_urbs(struct usb_anchor *anchor)
 {
@@ -597,6 +609,9 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs
  * from the back of the queue. This function is asynchronous.
  * The unlinking is just tiggered. It may happen after this
  * function has returned.
+ *
+ * This routine should not be called by a driver after its disconnect
+ * method has returned.
  */
 void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
 {

-- 

  parent reply	other threads:[~2008-11-04 23:39 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20081104232144.186593464@mini.kroah.org>
2008-11-04 23:30 ` [patch 00/57] 2.6.27-stable review Greg KH
2008-11-04 23:30   ` [patch 01/57] agp: Fix stolen memory counting on G4X Greg KH
2008-11-04 23:30   ` [patch 02/57] SCSI: sd: Fix handling of NO_SENSE check condition Greg KH
2008-11-04 23:31   ` [patch 03/57] S390: Fix sysdev class file creation Greg KH
2008-11-04 23:31   ` [patch 04/57] sysfs: Fix return values for sysdev_store_{ulong, int} Greg KH
2008-11-04 23:31   ` [patch 05/57] ipmi: add MODULE_ALIAS to load ipmi_devintf with ipmi_si Greg KH
2008-11-04 23:31   ` Greg KH [this message]
2008-11-04 23:31   ` [patch 07/57] ALSA: hda - Add reboot notifier Greg KH
2008-11-04 23:31   ` [patch 08/57] kbuild: mkspec - fix build rpm Greg KH
2008-11-04 23:31   ` [patch 09/57] x86: fix /dev/mem mmap breakage when PAT is disabled Greg KH
2008-11-04 23:31   ` [patch 10/57] atl1: fix vlan tag regression Greg KH
2008-11-04 23:31   ` [patch 11/57] libertas: fix buffer overrun Greg KH
2008-11-04 23:31   ` [patch 12/57] Revert "HID: Invert HWHEEL mappings for some Logitech mice" Greg KH
2008-11-04 23:31   ` [patch 13/57] libata: initialize port_task when !CONFIG_ATA_SFF Greg KH
2008-11-04 23:31   ` [patch 14/57] syncookies: fix inclusion of tcp options in syn-ack Greg KH
2008-11-04 23:31   ` [patch 15/57] tcp: Restore ordering of TCP options for the sake of inter-operability Greg KH
2008-11-04 23:31   ` [patch 16/57] tcpv6: fix option space offsets with md5 Greg KH
2008-11-04 23:31   ` [patch 17/57] pkt_sched: sch_generic: Fix oops in sch_teql Greg KH
2008-11-04 23:31   ` [patch 18/57] sparc64: Fix race in arch/sparc64/kernel/trampoline.S Greg KH
2008-11-04 23:31   ` [patch 19/57] math-emu: Fix signalling of underflow and inexact while packing result Greg KH
2008-11-04 23:31   ` [patch 20/57] firewire: fix setting tag and sy in iso transmission Greg KH
2008-11-04 23:31   ` [patch 21/57] firewire: fix ioctl() return code Greg KH
2008-11-04 23:31   ` [patch 22/57] firewire: Survive more than 256 bus resets Greg KH
2008-11-04 23:31   ` [patch 23/57] firewire: fix struct fw_node memory leak Greg KH
2008-11-04 23:31   ` [patch 24/57] firewire: fw-sbp2: delay first login to avoid retries Greg KH
2008-11-04 23:31   ` [patch 25/57] firewire: fw-sbp2: fix races Greg KH
2008-11-04 23:31   ` [patch 26/57] ACPI: Always report a sync event after a lid state change Greg KH
2008-11-04 23:31   ` [patch 27/57] powerpc: fix i2c on PPC linkstation / kurobox machines Greg KH
2008-11-04 23:31   ` [patch 28/57] powerpc: Reserve in bootmem lmb reserved regions that cross NUMA nodes Greg KH
2008-11-04 23:32   ` [patch 29/57] powerpc/numa: Make memory reserve code more robust Greg KH
2008-11-04 23:32   ` [patch 30/57] powerpc: Dont use a 16G page if beyond mem= limits Greg KH
2008-11-04 23:32   ` [patch 31/57] i2c: The i2c mailing list is moving Greg KH
2008-11-04 23:32   ` [patch 32/57] scx200_i2c: Add missing class parameter Greg KH
2008-11-04 23:32   ` [patch 33/57] ALSA: use correct lock in snd_ctl_dev_disconnect() Greg KH
2008-11-04 23:32   ` [patch 34/57] V4L: pvrusb2: Keep MPEG PTSs from drifting away Greg KH
2008-11-04 23:32   ` [patch 35/57] DVB: s5h1411: bugfix: Setting serial or parallel mode could destroy bits Greg KH
2008-11-04 23:32   ` [patch 36/57] DVB: s5h1411: Perform s5h1411 soft reset after tuning Greg KH
2008-11-04 23:32   ` [patch 37/57] DVB: s5h1411: Power down s5h1411 when not in use Greg KH
2008-11-04 23:32   ` [patch 38/57] PCI: fix 64-vbit prefetchable memory resource BARs Greg KH
2008-11-04 23:32   ` [patch 39/57] sched: disable the hrtick for now Greg KH
2008-11-04 23:33   ` [patch 40/57] sched_clock: prevent scd->clock from moving backwards Greg KH
2008-11-04 23:33   ` [patch 41/57] x86: avoid dereferencing beyond stack + THREAD_SIZE Greg KH
2008-11-04 23:33   ` [patch 42/57] rtc-cmos: look for PNP RTC first, then for platform RTC Greg KH
2008-11-04 23:33   ` [patch 43/57] USB: storage: Avoid I/O errors when issuing SCSI ioctls to JMicron USB/ATA bridge Greg KH
2008-11-04 23:33   ` [patch 44/57] x86: register a platform RTC device if PNP doesnt describe it Greg KH
2008-11-04 23:33   ` [patch 45/57] sata_promise: add ATA engine reset to reset ops Greg KH
2008-11-04 23:33   ` [patch 46/57] sata_nv: fix generic, nf2/3 detection regression Greg KH
2008-11-04 23:33   ` [patch 47/57] ACPI: EC: do transaction from interrupt context Greg KH
2008-11-04 23:33   ` [patch 48/57] ACPI: EC: Rename some variables Greg KH
2008-11-04 23:33   ` [patch 49/57] ACPI: EC: Check for IBF=0 periodically if not in GPE mode Greg KH
2008-11-04 23:33   ` [patch 50/57] libata: Fix LBA48 on pata_it821x RAID volumes Greg KH
2008-11-04 23:33   ` [patch 51/57] ACPI: Ingore the RESET_REG_SUP bit when using ACPI reset mechanism Greg KH
2008-11-05  0:48     ` Zhao Yakui
2008-11-05  1:02       ` Greg KH
2008-11-04 23:33   ` [patch 52/57] ACPI: Clear WAK_STS on resume Greg KH
2008-11-04 23:33   ` [patch 53/57] Input: atkbd - expand Latitudes force release quirk to other Dells Greg KH
2008-11-04 23:33   ` [patch 54/57] hfsplus: fix Buffer overflow with a corrupted image Greg KH
2008-11-04 23:33   ` [patch 55/57] hfsplus: check read_mapping_page() return value Greg KH
2008-11-04 23:33   ` [patch 56/57] bonding: fix panic when taking bond interface down before removing module Greg KH
2008-11-04 23:33   ` [patch 57/57] file caps: always start with clear bprm->caps_* Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20081104233109.GG659@suse.de \
    --to=gregkh@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=cavokz@gmail.com \
    --cc=cebbert@redhat.com \
    --cc=chuckw@quantumlinux.com \
    --cc=davej@redhat.com \
    --cc=eteo@redhat.com \
    --cc=jake@lwn.net \
    --cc=jejb@kernel.org \
    --cc=jmforbes@linuxtx.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mkrufky@linuxtv.org \
    --cc=rbranco@la.checkpoint.com \
    --cc=rdunlap@xenotime.net \
    --cc=reviews@ml.cw.f00f.org \
    --cc=stable@kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=torvalds@linux-foundation.org \
    --cc=tytso@mit.edu \
    --cc=w@1wt.eu \
    --cc=zwane@arm.linux.org.uk \
    --subject='Re: [patch 06/57] USB: fix crash when URBs are unlinked after the device is gone' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).