Linux Input/HID development
 help / color / mirror / Atom feed
* [patch]race between open and disconnect in usbhid
@ 2008-03-31 13:35 Oliver Neukum
  2008-03-31 13:23 ` Jiri Kosina
  0 siblings, 1 reply; 5+ messages in thread
From: Oliver Neukum @ 2008-03-31 13:35 UTC (permalink / raw)
  To: jkosina-AlSwsSmVLrQ, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA

There is a window:

task A					task B
spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
usb_set_intfdata(intf, NULL);
spin_unlock_irq(&usbhid->inlock);
usb_kill_urb(usbhid->urbin);
usb_kill_urb(usbhid->urbout);
usb_kill_urb(usbhid->urbctrl);

del_timer_sync(&usbhid->io_retry);
cancel_work_sync(&usbhid->reset_work);

						if (!hid->open++) {
							res = usb_autopm_get_interface(usbhid->intf);
							if (res < 0) {
								hid->open--;
								return -EIO;
							}
						}
						if (hid_start_in(hid))

if (hid->claimed & HID_CLAIMED_INPUT)
	hidinput_disconnect(hid);

in which an open() to an already disconnected device will submit an URB
to an undead device. In case disconnect() was called by an ioctl, this'll
oops. Fix by introducing a reliable flag an checking it in hid_start_in().

Signed-off-by: Oliver Neukum <oneukum-l3A5Bk7waGM@public.gmane.org>

----

--- linux-2.6.25-rc7-vanilla/drivers/hid/usbhid/usbhid.h	2007-07-09 01:32:17.000000000 +0200
+++ linux-2.6.25-rc7-work/drivers/hid/usbhid/usbhid.h	2008-03-31 13:45:25.000000000 +0200
@@ -77,6 +77,7 @@
 	unsigned long stop_retry;                                       /* Time to give up, in jiffies */
 	unsigned int retry_delay;                                       /* Delay length in ms */
 	struct work_struct reset_work;                                  /* Task context for resets */
+	char disconnected:1;						/* indicates undead device - no use */
 
 };
 
--- linux-2.6.25-rc7-vanilla/drivers/hid/usbhid/hid-core.c	2008-03-31 15:20:58.000000000 +0200
+++ linux-2.6.25-rc7-work/drivers/hid/usbhid/hid-core.c	2008-03-31 13:45:10.000000000 +0200
@@ -82,6 +82,7 @@
 
 	spin_lock_irqsave(&usbhid->inlock, flags);
 	if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
+			!usbhid->disconnected &&
 			!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
 		rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
 		if (rc != 0)
@@ -155,7 +156,7 @@
 	spin_lock_irqsave(&usbhid->inlock, flags);
 
 	/* Stop when disconnected */
-	if (usb_get_intfdata(usbhid->intf) == NULL)
+	if (usbhid->disconnected)
 		goto done;
 
 	/* If it has been a while since the last error, we'll assume
@@ -932,6 +933,7 @@
 
 	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
 	usb_set_intfdata(intf, NULL);
+	usbhid->disconnected = 1;
 	spin_unlock_irq(&usbhid->inlock);
 	usb_kill_urb(usbhid->urbin);
 	usb_kill_urb(usbhid->urbout);
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-03-31 14:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-31 13:35 [patch]race between open and disconnect in usbhid Oliver Neukum
2008-03-31 13:23 ` Jiri Kosina
2008-03-31 13:47   ` Oliver Neukum
     [not found]     ` <200803311547.56448.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
2008-03-31 13:35       ` Jiri Kosina
     [not found]         ` <Pine.LNX.4.64.0803311534240.5541-YCXOAqNspd+N3ZZ/Hiejyg@public.gmane.org>
2008-03-31 14:25           ` Oliver Neukum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox