aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2008-06-24 14:47:19 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-07-21 18:16:42 -0400
commitd64aac36394b3c26db53538bfedd8444a3a2206e (patch)
treeea532edd1cebaf62ba6f72b4c0f907fbf2b37cde
parent61ad04a89f0e3e6adaed0d9adfc0c9b431ccbb92 (diff)
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>
-rw-r--r--drivers/usb/core/devio.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 57bedcebf96c..c44e98f6099e 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -562,7 +562,6 @@ static struct usb_device *usbdev_lookup_by_devt(dev_t devt)
562 dev = bus_find_device(&usb_bus_type, NULL, (void *) devt, match_devt); 562 dev = bus_find_device(&usb_bus_type, NULL, (void *) devt, match_devt);
563 if (!dev) 563 if (!dev)
564 return NULL; 564 return NULL;
565 put_device(dev);
566 return container_of(dev, struct usb_device, dev); 565 return container_of(dev, struct usb_device, dev);
567} 566}
568 567
@@ -591,16 +590,21 @@ static int usbdev_open(struct inode *inode, struct file *file)
591 dev = usbdev_lookup_by_devt(inode->i_rdev); 590 dev = usbdev_lookup_by_devt(inode->i_rdev);
592#ifdef CONFIG_USB_DEVICEFS 591#ifdef CONFIG_USB_DEVICEFS
593 /* procfs file */ 592 /* procfs file */
594 if (!dev) 593 if (!dev) {
595 dev = inode->i_private; 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#endif 601#endif
597 if (!dev) 602 if (!dev || dev->state == USB_STATE_NOTATTACHED)
598 goto out; 603 goto out;
599 ret = usb_autoresume_device(dev); 604 ret = usb_autoresume_device(dev);
600 if (ret) 605 if (ret)
601 goto out; 606 goto out;
602 607
603 usb_get_dev(dev);
604 ret = 0; 608 ret = 0;
605 ps->dev = dev; 609 ps->dev = dev;
606 ps->file = file; 610 ps->file = file;
@@ -620,8 +624,10 @@ static int usbdev_open(struct inode *inode, struct file *file)
620 list_add_tail(&ps->list, &dev->filelist); 624 list_add_tail(&ps->list, &dev->filelist);
621 file->private_data = ps; 625 file->private_data = ps;
622 out: 626 out:
623 if (ret) 627 if (ret) {
624 kfree(ps); 628 kfree(ps);
629 usb_put_dev(dev);
630 }
625 mutex_unlock(&usbfs_mutex); 631 mutex_unlock(&usbfs_mutex);
626 unlock_kernel(); 632 unlock_kernel();
627 return ret; 633 return ret;