From d64aac36394b3c26db53538bfedd8444a3a2206e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 24 Jun 2008 14:47:19 -0400 Subject: 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 Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/usb/core/devio.c') 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) dev = bus_find_device(&usb_bus_type, NULL, (void *) devt, match_devt); if (!dev) return NULL; - put_device(dev); return container_of(dev, struct usb_device, dev); } @@ -591,16 +590,21 @@ static int usbdev_open(struct inode *inode, struct file *file) dev = usbdev_lookup_by_devt(inode->i_rdev); #ifdef CONFIG_USB_DEVICEFS /* procfs file */ - if (!dev) + if (!dev) { dev = inode->i_private; + if (dev && dev->usbfs_dentry && + dev->usbfs_dentry->d_inode == inode) + usb_get_dev(dev); + else + dev = NULL; + } #endif - if (!dev) + if (!dev || dev->state == USB_STATE_NOTATTACHED) goto out; ret = usb_autoresume_device(dev); if (ret) goto out; - usb_get_dev(dev); ret = 0; ps->dev = dev; ps->file = file; @@ -620,8 +624,10 @@ static int usbdev_open(struct inode *inode, struct file *file) list_add_tail(&ps->list, &dev->filelist); file->private_data = ps; out: - if (ret) + if (ret) { kfree(ps); + usb_put_dev(dev); + } mutex_unlock(&usbfs_mutex); unlock_kernel(); return ret; -- cgit v1.2.3