Re: [GIT PATCH] USB patches for 2.6.33-git

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2009-12-14 at 20:36 -0800, Linus Torvalds wrote:
> 
> On Mon, 14 Dec 2009, Russ Dill wrote:
> > @@ -144,10 +144,9 @@ static int __find_interface(struct device *dev, void *data)
> >  		return 0;
> >  
> >  	intf = to_usb_interface(dev);
> > -	if (intf->minor != -1 && intf->minor == arg->minor) {
> > -		arg->interface = intf;
> > +	if (intf->minor != -1 && intf->minor == arg->minor &&
> > +		dev->driver == arg->drv)
> >  		return 1;
> > -	}
> >  	return 0;
> >  }
> 
> Btw, can we please write this somewhat more readably, and just do
> 
> 	if (dev->driver != arg->drv)
> 		return 0;
> 	intf = to_usb_interface(dev);
> 	return intf->minor == arg->minor;
> 
> because the whole "intf->minor != -1" thing is pointless (we're going to 
> test it against 'arg->minor', and if that is -1, then the caller damn well 
> gets what he deserves anyway).
> 
> This way there are no complex multi-line crud expressions, and it all 
> looks simpler. No?

Yup.

From 41e394bc38b9d5224cc5e8013f45e769910a114e Mon Sep 17 00:00:00 2001
From: Russ Dill <Russ.Dill@xxxxxxxxx>
Date: Wed, 18 Nov 2009 10:31:27 -0700
Subject: [PATCH] Close usb_find_interface race v3

USB drivers that create character devices call usb_register_dev in their
probe function. This associates the usb_interface device with that minor
number and creates the character device and announces it to the world.
However, the driver's probe function is called before the new
usb_interface is added to the driver's klist_devices.

This is a problem because userspace will respond to the character device
creation announcement by opening the character device. The driver's open
function will the call usb_find_interface to find the usb_interface
associated with that minor number. usb_find_interface will walk the
driver's list of devices and find the usb_interface with the matching
minor number.

Because the announcement happens before the usb_interface is added to the
driver's klist_devices, a race condition exists. A straightforward fix
is to walk the list of devices on usb_bus_type instead since the device
is added to that list before the announcement occurs.

bus_find_device calls get_device to bump the reference count on the found
device. It is arguable that the reference count should be dropped by the
caller of usb_find_interface instead of usb_find_interface, however,
the current users of usb_find_interface do not expect this.

The original version of this patch only matched against minor number
instead of driver and minor number. This version matches against both.

Signed-off-by: Russ Dill <Russ.Dill@xxxxxxxxx>
---
 drivers/usb/core/usb.c |   31 ++++++++++++++++---------------
 1 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index b1b85ab..52e5e31 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting);
 
 struct find_interface_arg {
 	int minor;
-	struct usb_interface *interface;
+	struct device_driver *drv;
 };
 
 static int __find_interface(struct device *dev, void *data)
@@ -143,12 +143,10 @@ static int __find_interface(struct device *dev, void *data)
 	if (!is_usb_interface(dev))
 		return 0;
 
+	if (dev->driver != arg->drv)
+		return 0;
 	intf = to_usb_interface(dev);
-	if (intf->minor != -1 && intf->minor == arg->minor) {
-		arg->interface = intf;
-		return 1;
-	}
-	return 0;
+	return intf->minor == arg->minor;
 }
 
 /**
@@ -156,21 +154,24 @@ static int __find_interface(struct device *dev, void *data)
  * @drv: the driver whose current configuration is considered
  * @minor: the minor number of the desired device
  *
- * This walks the driver device list and returns a pointer to the interface
- * with the matching minor.  Note, this only works for devices that share the
- * USB major number.
+ * This walks the bus device list and returns a pointer to the interface
+ * with the matching minor and driver.  Note, this only works for devices
+ * that share the USB major number.
  */
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
 	struct find_interface_arg argb;
-	int retval;
+	struct device *dev;
 
 	argb.minor = minor;
-	argb.interface = NULL;
-	/* eat the error, it will be in argb.interface */
-	retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb,
-					__find_interface);
-	return argb.interface;
+	argb.drv = &drv->drvwrap.driver;
+
+	dev = bus_find_device(&usb_bus_type, NULL, &argb, __find_interface);
+
+	/* Drop reference count from bus_find_device */
+	put_device(dev);
+
+	return dev ? to_usb_interface(dev) : NULL;
 }
 EXPORT_SYMBOL_GPL(usb_find_interface);
 
-- 
1.6.5




Attachment: signature.asc
Description: This is a digitally signed message part


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux