Skip to content

Commit f2d8c26

Browse files
AlanSterngregkh
authored andcommitted
usb: gadget: Fix non-unique driver names in raw-gadget driver
In a report for a separate bug (which has already been fixed by commit 5f0b5f4 "usb: gadget: fix race when gadget driver register via ioctl") in the raw-gadget driver, the syzbot console log included error messages caused by attempted registration of a new driver with the same name as an existing driver: > kobject_add_internal failed for raw-gadget with -EEXIST, don't try to register things with the same name in the same directory. > UDC core: USB Raw Gadget: driver registration failed: -17 > misc raw-gadget: fail, usb_gadget_register_driver returned -17 These errors arise because raw_gadget.c registers a separate UDC driver for each of the UDC instances it creates, but these drivers all have the same name: "raw-gadget". Until recently this wasn't a problem, but when the "gadget" bus was added and UDC drivers were registered on this bus, it became possible for name conflicts to cause the registrations to fail. The reason is simply that the bus code in the driver core uses the driver name as a sysfs directory name (e.g., /sys/bus/gadget/drivers/raw-gadget/), and you can't create two directories with the same pathname. To fix this problem, the driver names used by raw-gadget are made distinct by appending a unique ID number: "raw-gadget.N", with a different value of N for each driver instance. And to avoid the proliferation of error handling code in the raw_ioctl_init() routine, the error return paths are refactored into the common pattern (goto statements leading to cleanup code at the end of the routine). Link: https://lore.kernel.org/all/[email protected]/ Fixes: fc274c1 "USB: gadget: Add a new bus for gadgets" CC: Andrey Konovalov <[email protected]> CC: <[email protected]> Reported-and-tested-by: [email protected] Reviewed-by: Andrey Konovalov <[email protected]> Acked-by: Hillf Danton <[email protected]> Signed-off-by: Alan Stern <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent dbab764 commit f2d8c26

File tree

1 file changed

+46
-16
lines changed

1 file changed

+46
-16
lines changed

drivers/usb/gadget/legacy/raw_gadget.c

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/ctype.h>
1212
#include <linux/debugfs.h>
1313
#include <linux/delay.h>
14+
#include <linux/idr.h>
1415
#include <linux/kref.h>
1516
#include <linux/miscdevice.h>
1617
#include <linux/module.h>
@@ -36,6 +37,9 @@ MODULE_LICENSE("GPL");
3637

3738
/*----------------------------------------------------------------------*/
3839

40+
static DEFINE_IDA(driver_id_numbers);
41+
#define DRIVER_DRIVER_NAME_LENGTH_MAX 32
42+
3943
#define RAW_EVENT_QUEUE_SIZE 16
4044

4145
struct raw_event_queue {
@@ -161,6 +165,9 @@ struct raw_dev {
161165
/* Reference to misc device: */
162166
struct device *dev;
163167

168+
/* Make driver names unique */
169+
int driver_id_number;
170+
164171
/* Protected by lock: */
165172
enum dev_state state;
166173
bool gadget_registered;
@@ -189,6 +196,7 @@ static struct raw_dev *dev_new(void)
189196
spin_lock_init(&dev->lock);
190197
init_completion(&dev->ep0_done);
191198
raw_event_queue_init(&dev->queue);
199+
dev->driver_id_number = -1;
192200
return dev;
193201
}
194202

@@ -199,6 +207,9 @@ static void dev_free(struct kref *kref)
199207

200208
kfree(dev->udc_name);
201209
kfree(dev->driver.udc_name);
210+
kfree(dev->driver.driver.name);
211+
if (dev->driver_id_number >= 0)
212+
ida_free(&driver_id_numbers, dev->driver_id_number);
202213
if (dev->req) {
203214
if (dev->ep0_urb_queued)
204215
usb_ep_dequeue(dev->gadget->ep0, dev->req);
@@ -422,6 +433,7 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
422433
struct usb_raw_init arg;
423434
char *udc_driver_name;
424435
char *udc_device_name;
436+
char *driver_driver_name;
425437
unsigned long flags;
426438

427439
if (copy_from_user(&arg, (void __user *)value, sizeof(arg)))
@@ -440,36 +452,44 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
440452
return -EINVAL;
441453
}
442454

455+
ret = ida_alloc(&driver_id_numbers, GFP_KERNEL);
456+
if (ret < 0)
457+
return ret;
458+
dev->driver_id_number = ret;
459+
460+
driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL);
461+
if (!driver_driver_name) {
462+
ret = -ENOMEM;
463+
goto out_free_driver_id_number;
464+
}
465+
snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX,
466+
DRIVER_NAME ".%d", dev->driver_id_number);
467+
443468
udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
444-
if (!udc_driver_name)
445-
return -ENOMEM;
469+
if (!udc_driver_name) {
470+
ret = -ENOMEM;
471+
goto out_free_driver_driver_name;
472+
}
446473
ret = strscpy(udc_driver_name, &arg.driver_name[0],
447474
UDC_NAME_LENGTH_MAX);
448-
if (ret < 0) {
449-
kfree(udc_driver_name);
450-
return ret;
451-
}
475+
if (ret < 0)
476+
goto out_free_udc_driver_name;
452477
ret = 0;
453478

454479
udc_device_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
455480
if (!udc_device_name) {
456-
kfree(udc_driver_name);
457-
return -ENOMEM;
481+
ret = -ENOMEM;
482+
goto out_free_udc_driver_name;
458483
}
459484
ret = strscpy(udc_device_name, &arg.device_name[0],
460485
UDC_NAME_LENGTH_MAX);
461-
if (ret < 0) {
462-
kfree(udc_driver_name);
463-
kfree(udc_device_name);
464-
return ret;
465-
}
486+
if (ret < 0)
487+
goto out_free_udc_device_name;
466488
ret = 0;
467489

468490
spin_lock_irqsave(&dev->lock, flags);
469491
if (dev->state != STATE_DEV_OPENED) {
470492
dev_dbg(dev->dev, "fail, device is not opened\n");
471-
kfree(udc_driver_name);
472-
kfree(udc_device_name);
473493
ret = -EINVAL;
474494
goto out_unlock;
475495
}
@@ -484,14 +504,24 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
484504
dev->driver.suspend = gadget_suspend;
485505
dev->driver.resume = gadget_resume;
486506
dev->driver.reset = gadget_reset;
487-
dev->driver.driver.name = DRIVER_NAME;
507+
dev->driver.driver.name = driver_driver_name;
488508
dev->driver.udc_name = udc_device_name;
489509
dev->driver.match_existing_only = 1;
490510

491511
dev->state = STATE_DEV_INITIALIZED;
512+
spin_unlock_irqrestore(&dev->lock, flags);
513+
return ret;
492514

493515
out_unlock:
494516
spin_unlock_irqrestore(&dev->lock, flags);
517+
out_free_udc_device_name:
518+
kfree(udc_device_name);
519+
out_free_udc_driver_name:
520+
kfree(udc_driver_name);
521+
out_free_driver_driver_name:
522+
kfree(driver_driver_name);
523+
out_free_driver_id_number:
524+
ida_free(&driver_id_numbers, dev->driver_id_number);
495525
return ret;
496526
}
497527

0 commit comments

Comments
 (0)