Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Stephen Ware and committed by
Greg Kroah-Hartman
84dcd594 71b7497c

+34 -20
+34 -20
drivers/usb/misc/vstusb.c
··· 59 59 #define USB_PRODUCT_LABPRO 0x0001 60 60 #define USB_PRODUCT_LABQUEST 0x0005 61 61 62 + #define VST_MAXBUFFER (64*1024) 63 + 62 64 static struct usb_device_id id_table[] = { 63 65 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB2000)}, 64 66 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_HR4000)}, ··· 75 73 MODULE_DEVICE_TABLE(usb, id_table); 76 74 77 75 struct vstusb_device { 76 + struct kref kref; 78 77 struct mutex lock; 79 78 struct usb_device *usb_dev; 80 79 char present; ··· 86 83 int wr_pipe; 87 84 int wr_timeout_ms; 88 85 }; 86 + #define to_vst_dev(d) container_of(d, struct vstusb_device, kref) 89 87 90 88 static struct usb_driver vstusb_driver; 89 + 90 + static void vstusb_delete(struct kref *kref) 91 + { 92 + struct vstusb_device *vstdev = to_vst_dev(kref); 93 + 94 + usb_put_dev(vstdev->usb_dev); 95 + kfree(vstdev); 96 + } 91 97 92 98 static int vstusb_open(struct inode *inode, struct file *file) 93 99 { ··· 126 114 return -EBUSY; 127 115 } 128 116 117 + /* increment our usage count */ 118 + kref_get(&vstdev->kref); 119 + 129 120 vstdev->isopen = 1; 130 121 131 122 /* save device in the file's private structure */ ··· 141 126 return 0; 142 127 } 143 128 144 - static int vstusb_close(struct inode *inode, struct file *file) 129 + static int vstusb_release(struct inode *inode, struct file *file) 145 130 { 146 131 struct vstusb_device *vstdev; 147 132 ··· 153 138 mutex_lock(&vstdev->lock); 154 139 155 140 vstdev->isopen = 0; 156 - file->private_data = NULL; 157 141 158 - /* if device is no longer present */ 159 - if (!vstdev->present) { 160 - mutex_unlock(&vstdev->lock); 161 - kfree(vstdev); 162 - } else 163 - mutex_unlock(&vstdev->lock); 142 + dev_dbg(&vstdev->usb_dev->dev, "%s: released\n", __func__); 143 + 144 + mutex_unlock(&vstdev->lock); 145 + 146 + kref_put(&vstdev->kref, vstusb_delete); 164 147 165 148 return 0; 166 149 } ··· 281 268 return -ENODEV; 282 269 283 270 /* verify that we actually want to read some data */ 284 - if (count == 0) 271 + if ((count == 0) || (count > VST_MAXBUFFER)) 285 272 return -EINVAL; 286 273 287 274 /* lock this object */ ··· 367 354 return -ENODEV; 368 355 369 356 /* verify that we actually have some data to write */ 370 - if (count == 0) 357 + if ((count == 0) || (count > VST_MAXBUFFER)) 371 358 return retval; 372 359 373 360 /* lock this object */ ··· 511 498 512 499 case IOCTL_VSTUSB_SEND_PIPE: 513 500 514 - if (usb_data.count == 0) { 501 + if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) { 515 502 mutex_unlock(&vstdev->lock); 516 503 retval = -EINVAL; 517 504 goto exit; ··· 564 551 break; 565 552 case IOCTL_VSTUSB_RECV_PIPE: 566 553 567 - if (usb_data.count == 0) { 554 + if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) { 568 555 mutex_unlock(&vstdev->lock); 569 556 retval = -EINVAL; 570 557 goto exit; ··· 646 633 .unlocked_ioctl = vstusb_ioctl, 647 634 .compat_ioctl = vstusb_ioctl, 648 635 .open = vstusb_open, 649 - .release = vstusb_close, 636 + .release = vstusb_release, 650 637 }; 651 638 652 639 static struct usb_class_driver usb_vstusb_class = { ··· 669 656 if (vstdev == NULL) 670 657 return -ENOMEM; 671 658 659 + /* must do usb_get_dev() prior to kref_init() since the kref_put() 660 + * release function will do a usb_put_dev() */ 661 + usb_get_dev(dev); 662 + kref_init(&vstdev->kref); 672 663 mutex_init(&vstdev->lock); 673 664 674 665 i = dev->descriptor.bcdDevice; ··· 693 676 "%s: Not able to get a minor for this device.\n", 694 677 __func__); 695 678 usb_set_intfdata(intf, NULL); 696 - kfree(vstdev); 679 + kref_put(&vstdev->kref, vstusb_delete); 697 680 return retval; 698 681 } 699 682 ··· 721 704 722 705 usb_kill_anchored_urbs(&vstdev->submitted); 723 706 724 - /* if the device is not opened, then we clean up right now */ 725 - if (!vstdev->isopen) { 726 - mutex_unlock(&vstdev->lock); 727 - kfree(vstdev); 728 - } else 729 - mutex_unlock(&vstdev->lock); 707 + mutex_unlock(&vstdev->lock); 730 708 709 + kref_put(&vstdev->kref, vstusb_delete); 731 710 } 711 + 732 712 } 733 713 734 714 static int vstusb_suspend(struct usb_interface *intf, pm_message_t message)