From: Oliver Neukum oneukum@suse.com
commit 3864d33943b4a76c6e64616280e98d2410b1190f upstream.
This driver is using a global variable. It cannot handle more than one device at a time. The issue has been existing since the dawn of the driver.
Signed-off-by: Oliver Neukum oneukum@suse.com Reported-by: syzbot+35f04d136fc975a70da4@syzkaller.appspotmail.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/rio500.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
--- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -464,15 +464,23 @@ static int probe_rio(struct usb_interfac { struct usb_device *dev = interface_to_usbdev(intf); struct rio_usb_data *rio = &rio_instance; - int retval; + int retval = 0;
- dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); + mutex_lock(&rio500_mutex); + if (rio->present) { + dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum); + retval = -EBUSY; + goto bail_out; + } else { + dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); + }
retval = usb_register_dev(intf, &usb_rio_class); if (retval) { dev_err(&dev->dev, "Not able to get a minor for this device.\n"); - return -ENOMEM; + retval = -ENOMEM; + goto bail_out; }
rio->rio_dev = dev; @@ -481,7 +489,8 @@ static int probe_rio(struct usb_interfac dev_err(&dev->dev, "probe_rio: Not enough memory for the output buffer\n"); usb_deregister_dev(intf, &usb_rio_class); - return -ENOMEM; + retval = -ENOMEM; + goto bail_out; } dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf);
@@ -490,7 +499,8 @@ static int probe_rio(struct usb_interfac "probe_rio: Not enough memory for the input buffer\n"); usb_deregister_dev(intf, &usb_rio_class); kfree(rio->obuf); - return -ENOMEM; + retval = -ENOMEM; + goto bail_out; } dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
@@ -498,8 +508,10 @@ static int probe_rio(struct usb_interfac
usb_set_intfdata (intf, rio); rio->present = 1; +bail_out: + mutex_unlock(&rio500_mutex);
- return 0; + return retval; }
static void disconnect_rio(struct usb_interface *intf)