lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1260849652.28808.1.camel@russ-laptop>
Date:	Mon, 14 Dec 2009 21:00:52 -0700
From:	Russ Dill <russ.dill@...il.com>
To:	Linus Torvalds <torvalds@...ux-foundation.org>
Cc:	Greg KH <greg@...ah.com>, Alan Stern <stern@...land.harvard.edu>,
	Greg KH <gregkh@...e.de>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
	linux-usb@...r.kernel.org
Subject: Re: [GIT PATCH] USB patches for 2.6.33-git

On Mon, 2009-12-14 at 20:17 -0700, russ.dill@...il.com wrote:
> 
> On Mon, Dec 14, 2009 at 8:09 PM, Linus Torvalds <torvalds@...ux-foundation.org> wrote:
> >
> >
> > On Mon, 14 Dec 2009, Linus Torvalds wrote:
> >>
> >> I'll double-check by reverting it from current -tip, but if you don't hear
> >> anything different from me, you can assume that that double-check
> >> succeeded and confirms that that commit really is the cause of my printer
> >> no longer working.
> >
> > Confirmed.
> >
> > With that commit reverted, everything works fine again. So it's definitely
> > a2582bd478c13c574d4c16ef1209d333f2a25935, although I have no idea _why_ it
> > causes problems.
> >
> > One thing I note is that it literally changed semantics, as per the
> > comment in there. It used to be:
> >
> >        This walks the driver device list and returns a pointer to the interface
> >        with the matching minor.
> >
> > and after that it is
> >
> >        This walks the bus device list and returns a pointer to the interface
> >        with the matching minor.
> >
> > Notice the "driver device list" -> "bus device list" change.
> >
> > Also notice that the minor number of my 'lp0' device is zero, so I could
> > easily imagine that some device without a driver at all or whatever will
> > have a zero there, and then it would return the wrong device entirely.
> >
> > So I really think that commit is very suspect. Not matching against the
> > driver that we passed in looks like some total screwup.
> >
> > But I don't know the code or the use. I do know that reverting it fixes
> > it.
> 
> Yes, you are right. Sorry for breaking your printer. There is both USB_MAJOR and USB_DEVICE_MAJOR. I haven't investigated it in great detail yet, but that seems likely to be the issue. I'll clean up the patch. And yes, it should definitely not be going into stable yet. Revert for now and I'll resubmit.


Here is a cleaned up patch that matches against minor and driver, not
just minor. I'll haven't test it yet, but will get a chance to tomorrow.

From 4441c99c80d8298a99b6f2fbd4ece9d3cfe7fd4d Mon Sep 17 00:00:00 2001
From: Russ Dill <Russ.Dill@...il.com>
Date: Wed, 18 Nov 2009 10:31:27 -0700
Subject: [PATCH] Close usb_find_interface race v2

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@...il.com>
---
 drivers/usb/core/usb.c |   28 +++++++++++++++-------------
 1 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index b1b85ab..2091fac 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)
@@ -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;
 }
 
@@ -156,21 +155,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



Download attachment "signature.asc" of type "application/pgp-signature" (198 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ