diff mbox series

[v3,3/4] usbcore/driver: Fix incorrect downcast

Message ID 20200922110703.720960-4-m.v.b@runbox.com
State Accepted
Commit 4df30e7603432704380b12fe40a604ee7f66746d
Headers show
Series [v3,1/4] Revert "usbip: Implement a match function to fix usbip" | expand

Commit Message

M. Vefa Bicakci Sept. 22, 2020, 11:07 a.m. UTC
This commit resolves a minor bug in the selection/discovery of more
specific USB device drivers for devices that are currently bound to
generic USB device drivers.

The bug is related to the way a candidate USB device driver is
compared against the generic USB device driver. The code in
is_dev_usb_generic_driver() assumes that the device driver in question
is a USB device driver by calling to_usb_device_driver(dev->driver)
to downcast; however I have observed that this assumption is not always
true, through code instrumentation.

This commit avoids the incorrect downcast altogether by comparing
the USB device's driver (i.e., dev->driver) to the generic USB
device driver directly. This method was suggested by Alan Stern.

This bug was found while investigating Andrey Konovalov's report
indicating usbip device driver misbehaviour with the recently merged
generic USB device driver selection feature. The report is linked
below.

Fixes: d5643d2249 ("USB: Fix device driver race")
Link: https://lore.kernel.org/linux-usb/CAAeHK+zOrHnxjRFs=OE8T=O9208B9HP_oo8RZpyVOZ9AJ54pAA@mail.gmail.com/
Cc: <stable@vger.kernel.org> # 5.8
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Bastien Nocera <hadess@hadess.net>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Valentina Manea <valentina.manea.m@gmail.com>
Cc: <syzkaller@googlegroups.com>
Signed-off-by: M. Vefa Bicakci <m.v.b@runbox.com>

---
v3: Simplify the device driver pointer comparison to avoid incorrect
    downcast, as suggested by Alan Stern. Minor edits to the commit
    message.

v2: Following Bastien Nocera's code review comment, use is_usb_device()
    to verify that a device is bound to a USB device driver (as opposed
    to, e.g., a USB interface driver) to avoid incorrect downcast.
---
 drivers/usb/core/driver.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

Comments

M. Vefa Bicakci Sept. 25, 2020, 4:31 p.m. UTC | #1
On 9/25/20 5:51 PM, Greg Kroah-Hartman wrote:
> On Tue, Sep 22, 2020 at 02:07:02PM +0300, M. Vefa Bicakci wrote:

>> This commit resolves a minor bug in the selection/discovery of more

>> specific USB device drivers for devices that are currently bound to

>> generic USB device drivers.

>>

>> The bug is related to the way a candidate USB device driver is

>> compared against the generic USB device driver. The code in

>> is_dev_usb_generic_driver() assumes that the device driver in question

>> is a USB device driver by calling to_usb_device_driver(dev->driver)

>> to downcast; however I have observed that this assumption is not always

>> true, through code instrumentation.

>>

>> This commit avoids the incorrect downcast altogether by comparing

>> the USB device's driver (i.e., dev->driver) to the generic USB

>> device driver directly. This method was suggested by Alan Stern.

>>

>> This bug was found while investigating Andrey Konovalov's report

>> indicating usbip device driver misbehaviour with the recently merged

>> generic USB device driver selection feature. The report is linked

>> below.

>>

>> Fixes: d5643d2249 ("USB: Fix device driver race")

> 

> Nit, this should have been:

> 	Fixes: d5643d2249b2 ("USB: Fix device driver race")

> 

> I'll go fix it up as my scripts are rejecting it as-is...


Noted; sorry for missing this. I will use 12 characters from now on.

I also wanted to thank you for committing the patches.

Vefa
gregkh@linuxfoundation.org Sept. 26, 2020, 5:37 a.m. UTC | #2
On Fri, Sep 25, 2020 at 07:31:44PM +0300, M. Vefa Bicakci wrote:
> On 9/25/20 5:51 PM, Greg Kroah-Hartman wrote:
> > On Tue, Sep 22, 2020 at 02:07:02PM +0300, M. Vefa Bicakci wrote:
> > > This commit resolves a minor bug in the selection/discovery of more
> > > specific USB device drivers for devices that are currently bound to
> > > generic USB device drivers.
> > > 
> > > The bug is related to the way a candidate USB device driver is
> > > compared against the generic USB device driver. The code in
> > > is_dev_usb_generic_driver() assumes that the device driver in question
> > > is a USB device driver by calling to_usb_device_driver(dev->driver)
> > > to downcast; however I have observed that this assumption is not always
> > > true, through code instrumentation.
> > > 
> > > This commit avoids the incorrect downcast altogether by comparing
> > > the USB device's driver (i.e., dev->driver) to the generic USB
> > > device driver directly. This method was suggested by Alan Stern.
> > > 
> > > This bug was found while investigating Andrey Konovalov's report
> > > indicating usbip device driver misbehaviour with the recently merged
> > > generic USB device driver selection feature. The report is linked
> > > below.
> > > 
> > > Fixes: d5643d2249 ("USB: Fix device driver race")
> > 
> > Nit, this should have been:
> > 	Fixes: d5643d2249b2 ("USB: Fix device driver race")
> > 
> > I'll go fix it up as my scripts are rejecting it as-is...
> 
> Noted; sorry for missing this. I will use 12 characters from now on.

No worries.  There's a nice git configuration line you can do that is
documented in the submitting patches file in the kernel documentation
directory, if you want to use that.  I have a alias that does it easily
as well as it gets annoying to have to type:

	git show -s --abbrev-commit --abbrev=12 --pretty=format:"%h (\"%s\")%n"

A lot :)

> I also wanted to thank you for committing the patches.

Thanks for fixing this all up!

greg k-h
diff mbox series

Patch

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 950044a6e77f..7d90cbe063ec 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -905,21 +905,14 @@  static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
 	return 0;
 }
 
-static bool is_dev_usb_generic_driver(struct device *dev)
-{
-	struct usb_device_driver *udd = dev->driver ?
-		to_usb_device_driver(dev->driver) : NULL;
-
-	return udd == &usb_generic_driver;
-}
-
 static int __usb_bus_reprobe_drivers(struct device *dev, void *data)
 {
 	struct usb_device_driver *new_udriver = data;
 	struct usb_device *udev;
 	int ret;
 
-	if (!is_dev_usb_generic_driver(dev))
+	/* Don't reprobe if current driver isn't usb_generic_driver */
+	if (dev->driver != &usb_generic_driver.drvwrap.driver)
 		return 0;
 
 	udev = to_usb_device(dev);