Skip to contentSkip to conversation

patch "USB: Proper handling of Race Condition when two USB class drivers try" added to usb-next

PATCH [email protected] 1 participant 1 message Mar 29, 2017

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

USB: Proper handling of Race Condition when two USB class drivers try

to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-next branch.

The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)

The patch will also be merged in the next major kernel release during the merge window.

If you have any questions about this process, please let me know.

Quoted 1 line

From 2f86a96be0ccb1302b7eee7855dbee5ce4dc5dfb Mon Sep 17 00:00:00 2001

From: Ajay Kaher <[email protected]>
Date: Tue, 28 Mar 2017 08:09:32 -0400
Subject: USB: Proper handling of Race Condition when two USB class drivers try
to call init_usb_class simultaneously

There is race condition when two USB class drivers try to call init_usb_class at the same time and leads to crash. code path: probe->usb_register_dev->init_usb_class

To solve this, mutex locking has been added in init_usb_class() and destroy_usb_class().

As pointed by Alan, removed "if (usb_class)" test from destroy_usb_class() because usb_class can never be NULL there.

---
 drivers/usb/core/file.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/usb/core/file.c +7 -2
index e26bd5e773ad..87ad6b6bfee8 100644
@@ -29,6 +29,7 @@
 #define MAX_USB_MINORS	256
 static const struct file_operations *usb_minors[MAX_USB_MINORS];
 static DECLARE_RWSEM(minor_rwsem);
+static DEFINE_MUTEX(init_usb_class_mutex);
 
 static int usb_open(struct inode *inode, struct file *file)
 {
@@ -111,8 +112,9 @@ static void release_usb_class(struct kref *kref)
 
 static void destroy_usb_class(void)
 {
-	if (usb_class)
-		kref_put(&usb_class->kref, release_usb_class);
+	mutex_lock(&init_usb_class_mutex);
+	kref_put(&usb_class->kref, release_usb_class);
+	mutex_unlock(&init_usb_class_mutex);
 }
 
 int usb_major_init(void)
@@ -173,7 +175,10 @@ int usb_register_dev(struct usb_interface *intf,
 	if (intf->minor >= 0)
 		return -EADDRINUSE;
 
+	mutex_lock(&init_usb_class_mutex);
 	retval = init_usb_class();
+	mutex_unlock(&init_usb_class_mutex);
+
 	if (retval)
 		return retval;
 
Signature · 1 line
2.12.1