aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Ware <stephen.ware@eqware.net>2008-10-08 13:53:56 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-10-17 17:41:04 -0400
commit84dcd594952bf9b95b3901516a61e57abdf54d62 (patch)
treec287500ddd5d4559a8313485e66cd224333281c1 /drivers
parent71b7497c078a97e2afb774ad7c1f8ff5bdda8a60 (diff)
USB: fix up problems in the vtusb driver
Add range check on buffer sizes passed in from user space (max is 8*PAGE_SIZE) which will work for the most common spectrometers even at pages as small as 1K. Add kref to vst device structure to preserve reference to the usb object until we truly are done with it. From: Stephen Ware <stephen.ware@eqware.net> From: Dennis O'Brien <dennis.obrien@eqware.net> Signed-off-by: Dennis O'Brien <dennis.obrien@eqware.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/misc/vstusb.c54
1 files changed, 34 insertions, 20 deletions
diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c
index 5ad75e4a0323..8648470c81ca 100644
--- a/drivers/usb/misc/vstusb.c
+++ b/drivers/usb/misc/vstusb.c
@@ -59,6 +59,8 @@
59#define USB_PRODUCT_LABPRO 0x0001 59#define USB_PRODUCT_LABPRO 0x0001
60#define USB_PRODUCT_LABQUEST 0x0005 60#define USB_PRODUCT_LABQUEST 0x0005
61 61
62#define VST_MAXBUFFER (64*1024)
63
62static struct usb_device_id id_table[] = { 64static struct usb_device_id id_table[] = {
63 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB2000)}, 65 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB2000)},
64 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_HR4000)}, 66 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_HR4000)},
@@ -73,6 +75,7 @@ static struct usb_device_id id_table[] = {
73MODULE_DEVICE_TABLE(usb, id_table); 75MODULE_DEVICE_TABLE(usb, id_table);
74 76
75struct vstusb_device { 77struct vstusb_device {
78 struct kref kref;
76 struct mutex lock; 79 struct mutex lock;
77 struct usb_device *usb_dev; 80 struct usb_device *usb_dev;
78 char present; 81 char present;
@@ -83,9 +86,18 @@ struct vstusb_device {
83 int wr_pipe; 86 int wr_pipe;
84 int wr_timeout_ms; 87 int wr_timeout_ms;
85}; 88};
89#define to_vst_dev(d) container_of(d, struct vstusb_device, kref)
86 90
87static struct usb_driver vstusb_driver; 91static struct usb_driver vstusb_driver;
88 92
93static void vstusb_delete(struct kref *kref)
94{
95 struct vstusb_device *vstdev = to_vst_dev(kref);
96
97 usb_put_dev(vstdev->usb_dev);
98 kfree(vstdev);
99}
100
89static int vstusb_open(struct inode *inode, struct file *file) 101static int vstusb_open(struct inode *inode, struct file *file)
90{ 102{
91 struct vstusb_device *vstdev; 103 struct vstusb_device *vstdev;
@@ -114,6 +126,9 @@ static int vstusb_open(struct inode *inode, struct file *file)
114 return -EBUSY; 126 return -EBUSY;
115 } 127 }
116 128
129 /* increment our usage count */
130 kref_get(&vstdev->kref);
131
117 vstdev->isopen = 1; 132 vstdev->isopen = 1;
118 133
119 /* save device in the file's private structure */ 134 /* save device in the file's private structure */
@@ -126,7 +141,7 @@ static int vstusb_open(struct inode *inode, struct file *file)
126 return 0; 141 return 0;
127} 142}
128 143
129static int vstusb_close(struct inode *inode, struct file *file) 144static int vstusb_release(struct inode *inode, struct file *file)
130{ 145{
131 struct vstusb_device *vstdev; 146 struct vstusb_device *vstdev;
132 147
@@ -138,14 +153,12 @@ static int vstusb_close(struct inode *inode, struct file *file)
138 mutex_lock(&vstdev->lock); 153 mutex_lock(&vstdev->lock);
139 154
140 vstdev->isopen = 0; 155 vstdev->isopen = 0;
141 file->private_data = NULL;
142 156
143 /* if device is no longer present */ 157 dev_dbg(&vstdev->usb_dev->dev, "%s: released\n", __func__);
144 if (!vstdev->present) { 158
145 mutex_unlock(&vstdev->lock); 159 mutex_unlock(&vstdev->lock);
146 kfree(vstdev); 160
147 } else 161 kref_put(&vstdev->kref, vstusb_delete);
148 mutex_unlock(&vstdev->lock);
149 162
150 return 0; 163 return 0;
151} 164}
@@ -268,7 +281,7 @@ static ssize_t vstusb_read(struct file *file, char __user *buffer,
268 return -ENODEV; 281 return -ENODEV;
269 282
270 /* verify that we actually want to read some data */ 283 /* verify that we actually want to read some data */
271 if (count == 0) 284 if ((count == 0) || (count > VST_MAXBUFFER))
272 return -EINVAL; 285 return -EINVAL;
273 286
274 /* lock this object */ 287 /* lock this object */
@@ -354,7 +367,7 @@ static ssize_t vstusb_write(struct file *file, const char __user *buffer,
354 return -ENODEV; 367 return -ENODEV;
355 368
356 /* verify that we actually have some data to write */ 369 /* verify that we actually have some data to write */
357 if (count == 0) 370 if ((count == 0) || (count > VST_MAXBUFFER))
358 return retval; 371 return retval;
359 372
360 /* lock this object */ 373 /* lock this object */
@@ -498,7 +511,7 @@ static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
498 511
499 case IOCTL_VSTUSB_SEND_PIPE: 512 case IOCTL_VSTUSB_SEND_PIPE:
500 513
501 if (usb_data.count == 0) { 514 if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) {
502 mutex_unlock(&vstdev->lock); 515 mutex_unlock(&vstdev->lock);
503 retval = -EINVAL; 516 retval = -EINVAL;
504 goto exit; 517 goto exit;
@@ -551,7 +564,7 @@ static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
551 break; 564 break;
552 case IOCTL_VSTUSB_RECV_PIPE: 565 case IOCTL_VSTUSB_RECV_PIPE:
553 566
554 if (usb_data.count == 0) { 567 if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) {
555 mutex_unlock(&vstdev->lock); 568 mutex_unlock(&vstdev->lock);
556 retval = -EINVAL; 569 retval = -EINVAL;
557 goto exit; 570 goto exit;
@@ -633,7 +646,7 @@ static const struct file_operations vstusb_fops = {
633 .unlocked_ioctl = vstusb_ioctl, 646 .unlocked_ioctl = vstusb_ioctl,
634 .compat_ioctl = vstusb_ioctl, 647 .compat_ioctl = vstusb_ioctl,
635 .open = vstusb_open, 648 .open = vstusb_open,
636 .release = vstusb_close, 649 .release = vstusb_release,
637}; 650};
638 651
639static struct usb_class_driver usb_vstusb_class = { 652static struct usb_class_driver usb_vstusb_class = {
@@ -656,6 +669,10 @@ static int vstusb_probe(struct usb_interface *intf,
656 if (vstdev == NULL) 669 if (vstdev == NULL)
657 return -ENOMEM; 670 return -ENOMEM;
658 671
672 /* must do usb_get_dev() prior to kref_init() since the kref_put()
673 * release function will do a usb_put_dev() */
674 usb_get_dev(dev);
675 kref_init(&vstdev->kref);
659 mutex_init(&vstdev->lock); 676 mutex_init(&vstdev->lock);
660 677
661 i = dev->descriptor.bcdDevice; 678 i = dev->descriptor.bcdDevice;
@@ -676,7 +693,7 @@ static int vstusb_probe(struct usb_interface *intf,
676 "%s: Not able to get a minor for this device.\n", 693 "%s: Not able to get a minor for this device.\n",
677 __func__); 694 __func__);
678 usb_set_intfdata(intf, NULL); 695 usb_set_intfdata(intf, NULL);
679 kfree(vstdev); 696 kref_put(&vstdev->kref, vstusb_delete);
680 return retval; 697 return retval;
681 } 698 }
682 699
@@ -704,14 +721,11 @@ static void vstusb_disconnect(struct usb_interface *intf)
704 721
705 usb_kill_anchored_urbs(&vstdev->submitted); 722 usb_kill_anchored_urbs(&vstdev->submitted);
706 723
707 /* if the device is not opened, then we clean up right now */ 724 mutex_unlock(&vstdev->lock);
708 if (!vstdev->isopen) {
709 mutex_unlock(&vstdev->lock);
710 kfree(vstdev);
711 } else
712 mutex_unlock(&vstdev->lock);
713 725
726 kref_put(&vstdev->kref, vstusb_delete);
714 } 727 }
728
715} 729}
716 730
717static int vstusb_suspend(struct usb_interface *intf, pm_message_t message) 731static int vstusb_suspend(struct usb_interface *intf, pm_message_t message)