Commit d64aac36394b3c26db53538bfedd8444a3a2206e

Authored by Alan Stern
Committed by Greg Kroah-Hartman
1 parent 61ad04a89f

usbfs: fix race between open and unregister

This patch (as1106) fixes a race between opening and unregistering
device files in usbfs.  The current code drops its reference to the
device and then reacquires it, ignoring the possibility that the
device structure might have been removed in the meantime.  It also
doesn't check whether the device is already in the NOTATTACHED state
when the file is opened.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 1 changed file with 11 additions and 5 deletions Side-by-side Diff

drivers/usb/core/devio.c
... ... @@ -562,7 +562,6 @@
562 562 dev = bus_find_device(&usb_bus_type, NULL, (void *) devt, match_devt);
563 563 if (!dev)
564 564 return NULL;
565   - put_device(dev);
566 565 return container_of(dev, struct usb_device, dev);
567 566 }
568 567  
569 568  
570 569  
571 570  
... ... @@ -591,16 +590,21 @@
591 590 dev = usbdev_lookup_by_devt(inode->i_rdev);
592 591 #ifdef CONFIG_USB_DEVICEFS
593 592 /* procfs file */
594   - if (!dev)
  593 + if (!dev) {
595 594 dev = inode->i_private;
  595 + if (dev && dev->usbfs_dentry &&
  596 + dev->usbfs_dentry->d_inode == inode)
  597 + usb_get_dev(dev);
  598 + else
  599 + dev = NULL;
  600 + }
596 601 #endif
597   - if (!dev)
  602 + if (!dev || dev->state == USB_STATE_NOTATTACHED)
598 603 goto out;
599 604 ret = usb_autoresume_device(dev);
600 605 if (ret)
601 606 goto out;
602 607  
603   - usb_get_dev(dev);
604 608 ret = 0;
605 609 ps->dev = dev;
606 610 ps->file = file;
607 611  
... ... @@ -620,8 +624,10 @@
620 624 list_add_tail(&ps->list, &dev->filelist);
621 625 file->private_data = ps;
622 626 out:
623   - if (ret)
  627 + if (ret) {
624 628 kfree(ps);
  629 + usb_put_dev(dev);
  630 + }
625 631 mutex_unlock(&usbfs_mutex);
626 632 unlock_kernel();
627 633 return ret;