aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorMing Lei <tom.leiming@gmail.com>2011-12-16 09:20:01 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-04 18:52:41 -0500
commit26c71a79cade5ccad80e0752cd82f3518df48fb3 (patch)
tree965a339ad5ef6a02635455394525e37141b86fef /drivers/usb
parente78832cdca2ddd23c15abaed642cad1a39b3e122 (diff)
USB: usb-skeleton.c: fix open/disconnect race
If usb device is disconnected between usb_get_intfdata() and kref_get() in skel_open(), kref_get may access a freed object. Also check if device is disconnected in ->open. Signed-off-by: Ming Lei <tom.leiming@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/usb-skeleton.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 32d6fc953904..3635f9e37559 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -27,6 +27,8 @@
27#define USB_SKEL_VENDOR_ID 0xfff0 27#define USB_SKEL_VENDOR_ID 0xfff0
28#define USB_SKEL_PRODUCT_ID 0xfff0 28#define USB_SKEL_PRODUCT_ID 0xfff0
29 29
30static DEFINE_MUTEX(skel_mutex);
31
30/* table of devices that work with this driver */ 32/* table of devices that work with this driver */
31static const struct usb_device_id skel_table[] = { 33static const struct usb_device_id skel_table[] = {
32 { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, 34 { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
@@ -100,18 +102,25 @@ static int skel_open(struct inode *inode, struct file *file)
100 goto exit; 102 goto exit;
101 } 103 }
102 104
105 mutex_lock(&skel_mutex);
103 dev = usb_get_intfdata(interface); 106 dev = usb_get_intfdata(interface);
104 if (!dev) { 107 if (!dev) {
108 mutex_unlock(&skel_mutex);
105 retval = -ENODEV; 109 retval = -ENODEV;
106 goto exit; 110 goto exit;
107 } 111 }
108 112
109 /* increment our usage count for the device */ 113 /* increment our usage count for the device */
110 kref_get(&dev->kref); 114 kref_get(&dev->kref);
115 mutex_unlock(&skel_mutex);
111 116
112 /* lock the device to allow correctly handling errors 117 /* lock the device to allow correctly handling errors
113 * in resumption */ 118 * in resumption */
114 mutex_lock(&dev->io_mutex); 119 mutex_lock(&dev->io_mutex);
120 if (!dev->interface) {
121 retval = -ENODEV;
122 goto out_err;
123 }
115 124
116 if (!dev->open_count++) { 125 if (!dev->open_count++) {
117 retval = usb_autopm_get_interface(interface); 126 retval = usb_autopm_get_interface(interface);
@@ -132,7 +141,11 @@ static int skel_open(struct inode *inode, struct file *file)
132 141
133 /* save our object in the file's private structure */ 142 /* save our object in the file's private structure */
134 file->private_data = dev; 143 file->private_data = dev;
144
145out_err:
135 mutex_unlock(&dev->io_mutex); 146 mutex_unlock(&dev->io_mutex);
147 if (retval)
148 kref_put(&dev->kref, skel_delete);
136 149
137exit: 150exit:
138 return retval; 151 return retval;
@@ -612,7 +625,6 @@ static void skel_disconnect(struct usb_interface *interface)
612 int minor = interface->minor; 625 int minor = interface->minor;
613 626
614 dev = usb_get_intfdata(interface); 627 dev = usb_get_intfdata(interface);
615 usb_set_intfdata(interface, NULL);
616 628
617 /* give back our minor */ 629 /* give back our minor */
618 usb_deregister_dev(interface, &skel_class); 630 usb_deregister_dev(interface, &skel_class);
@@ -624,8 +636,12 @@ static void skel_disconnect(struct usb_interface *interface)
624 636
625 usb_kill_anchored_urbs(&dev->submitted); 637 usb_kill_anchored_urbs(&dev->submitted);
626 638
639 mutex_lock(&skel_mutex);
640 usb_set_intfdata(interface, NULL);
641
627 /* decrement our usage count */ 642 /* decrement our usage count */
628 kref_put(&dev->kref, skel_delete); 643 kref_put(&dev->kref, skel_delete);
644 mutex_unlock(&skel_mutex);
629 645
630 dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor); 646 dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor);
631} 647}