From 86286883fc8218c81cc1deb04cd1b4a8464bba6f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 2 Jul 2009 11:36:30 +0200 Subject: USB: usbtmc can do IO to device after disconnect usbtmc will happily complete read/write requests even after disconnect has returned. The fix is to introduce a flag. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index b09a527f7341..0c9df97f6775 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -86,6 +86,8 @@ struct usbtmc_device_data { bool TermCharEnabled; bool auto_abort; + bool zombie; /* fd of disconnected device */ + struct usbtmc_dev_capabilities capabilities; struct kref kref; struct mutex io_mutex; /* only one i/o function running at a time */ @@ -384,6 +386,10 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, return -ENOMEM; mutex_lock(&data->io_mutex); + if (data->zombie) { + retval = -ENODEV; + goto exit; + } remaining = count; done = 0; @@ -496,6 +502,10 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, return -ENOMEM; mutex_lock(&data->io_mutex); + if (data->zombie) { + retval = -ENODEV; + goto exit; + } remaining = count; done = 0; @@ -925,6 +935,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) data = file->private_data; mutex_lock(&data->io_mutex); + if (data->zombie) { + retval = -ENODEV; + goto skip_io_on_zombie; + } switch (cmd) { case USBTMC_IOCTL_CLEAR_OUT_HALT: @@ -952,6 +966,7 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } +skip_io_on_zombie: mutex_unlock(&data->io_mutex); return retval; } @@ -995,6 +1010,7 @@ static int usbtmc_probe(struct usb_interface *intf, usb_set_intfdata(intf, data); kref_init(&data->kref); mutex_init(&data->io_mutex); + data->zombie = 0; /* Initialize USBTMC bTag and other fields */ data->bTag = 1; @@ -1065,6 +1081,9 @@ static void usbtmc_disconnect(struct usb_interface *intf) usb_deregister_dev(intf, &usbtmc_class); sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); + mutex_lock(&data->io_mutex); + data->zombie = 1; + mutex_unlock(&data->io_mutex); kref_put(&data->kref, usbtmc_delete); } -- cgit v1.2.2 From a4708103adeaf5731c329b37b0a2b397f814c55c Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 2 Jul 2009 11:44:33 +0200 Subject: USB: suspend/resume support for usbtmc a class driver should have suspend/resume. This makes sure we don't see a virtual disconnect unnecessarily. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 0c9df97f6775..4f0858fbf980 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1087,11 +1087,24 @@ static void usbtmc_disconnect(struct usb_interface *intf) kref_put(&data->kref, usbtmc_delete); } +static int usbtmc_suspend (struct usb_interface *intf, pm_message_t message) +{ + /* this driver does not have pending URBs */ + return 0; +} + +static int usbtmc_resume (struct usb_interface *intf) +{ + return 0; +} + static struct usb_driver usbtmc_driver = { .name = "usbtmc", .id_table = usbtmc_devices, .probe = usbtmc_probe, - .disconnect = usbtmc_disconnect + .disconnect = usbtmc_disconnect, + .suspend = usbtmc_suspend, + .resume = usbtmc_resume, }; static int __init usbtmc_init(void) -- cgit v1.2.2 From 665d7662d15441b4b3e54131a9418a1a198d0d31 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Wed, 22 Jul 2009 17:39:42 +0200 Subject: USB: usbtmc: sanity checks for DEV_DEP_MSG_IN urbs According to the specifications, an instrument should not return more data in a DEV_DEP_MSG_IN urb than requested. However, some instruments can send more than requested. This could cause the kernel to write the extra data past the end of the buffer provided by read(). Fix this by checking that the value of the TranserSize field is not larger than the urb itself and not larger than the size of the userspace buffer. Also correctly decrement the remaining size of the buffer when userspace read()s more than USBTMC_SIZE_IOBUFFER. Signed-off-by: Guus Sliepen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 4f0858fbf980..5bab8e596c88 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -369,13 +369,13 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, { struct usbtmc_device_data *data; struct device *dev; - unsigned long int n_characters; + u32 n_characters; u8 *buffer; int actual; - int done; - int remaining; + size_t done; + size_t remaining; int retval; - int this_part; + size_t this_part; /* Get pointer to private data structure */ data = filp->private_data; @@ -461,6 +461,18 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, (buffer[6] << 16) + (buffer[7] << 24); + /* Ensure the instrument doesn't lie about it */ + if(n_characters > actual - 12) { + dev_err(dev, "Device lies about message size: %zu > %zu\n", n_characters, actual - 12); + n_characters = actual - 12; + } + + /* Ensure the instrument doesn't send more back than requested */ + if(n_characters > this_part) { + dev_err(dev, "Device returns more than requested: %zu > %zu\n", done + n_characters, done + this_part); + n_characters = this_part; + } + /* Copy buffer to user space */ if (copy_to_user(buf + done, &buffer[12], n_characters)) { /* There must have been an addressing problem */ @@ -471,6 +483,8 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, done += n_characters; if (n_characters < USBTMC_SIZE_IOBUFFER) remaining = 0; + else + remaining -= n_characters; } /* Update file position value */ -- cgit v1.2.2 From a2fbf10eba3a38407e3984bc9503342de2b5e399 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 28 Jul 2009 11:22:41 -0700 Subject: USB: usbtmc: fix printk format warnings Fix printk format warnings: drivers/usb/class/usbtmc.c:466: warning: format '%zu' expects type 'size_t', but argument 4 has type 'u32' drivers/usb/class/usbtmc.c:466: warning: format '%zu' expects type 'size_t', but argument 5 has type 'int' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 5bab8e596c88..40ef4da786d8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -463,7 +463,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, /* Ensure the instrument doesn't lie about it */ if(n_characters > actual - 12) { - dev_err(dev, "Device lies about message size: %zu > %zu\n", n_characters, actual - 12); + dev_err(dev, "Device lies about message size: %u > %d\n", n_characters, actual - 12); n_characters = actual - 12; } -- cgit v1.2.2 From c2cd26e15b84b964c489f2aff278cdaf03840c93 Mon Sep 17 00:00:00 2001 From: Steve Holland Date: Thu, 18 Jun 2009 17:37:49 -0500 Subject: USB: usbtmc: Fix short reads in usbtmc_read() The header size should not be included in the number of bytes requested of the instrument Signed-off-by: Steve Holland Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 40ef4da786d8..f2fde7cd6109 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -407,10 +407,10 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, buffer[1] = data->bTag; buffer[2] = ~(data->bTag); buffer[3] = 0; /* Reserved */ - buffer[4] = (this_part - 12 - 3) & 255; - buffer[5] = ((this_part - 12 - 3) >> 8) & 255; - buffer[6] = ((this_part - 12 - 3) >> 16) & 255; - buffer[7] = ((this_part - 12 - 3) >> 24) & 255; + buffer[4] = (this_part) & 255; + buffer[5] = ((this_part) >> 8) & 255; + buffer[6] = ((this_part) >> 16) & 255; + buffer[7] = ((this_part) >> 24) & 255; buffer[8] = data->TermCharEnabled * 2; /* Use term character? */ buffer[9] = data->TermChar; -- cgit v1.2.2 From 92d07e422df3cc5370d0d9b95a671abb69d50ef1 Mon Sep 17 00:00:00 2001 From: Steve Holland Date: Thu, 18 Jun 2009 17:37:49 -0500 Subject: USB: usbtmc: inhibit corruption Limit data copied to userspace to amount requested. Prevents a faulty instrument from overwriting user memory. Signed-off-by: Steve Holland Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index f2fde7cd6109..91d3a94eeaa0 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -473,6 +473,10 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, n_characters = this_part; } + /* Bound amount of data received by amount of data requested */ + if (n_characters > this_part) + n_characters = this_part; + /* Copy buffer to user space */ if (copy_to_user(buf + done, &buffer[12], n_characters)) { /* There must have been an addressing problem */ -- cgit v1.2.2 From 4143d178e7b39c00d5277040c69a1522c4d98871 Mon Sep 17 00:00:00 2001 From: Steve Holland Date: Thu, 18 Jun 2009 17:37:49 -0500 Subject: USB: usbtmc: correct termination condition for reads. Follow T&M convention of obeying EOM flag. Avoid exception cases where instrument response size matches a buffer size. Signed-off-by: Steve Holland Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 91d3a94eeaa0..6395f22a58e1 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -485,7 +485,8 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, } done += n_characters; - if (n_characters < USBTMC_SIZE_IOBUFFER) + /* Terminate if end-of-message bit recieved from device */ + if ((buffer[8] & 0x01) && (actual >= n_characters + 12)) remaining = 0; else remaining -= n_characters; -- cgit v1.2.2 From d0a38365d9585bf3fb71f7c57fd532441a14f3e8 Mon Sep 17 00:00:00 2001 From: Gergely Imreh Date: Mon, 7 Sep 2009 10:47:01 +0800 Subject: USB: fix USBTMC get_capabilities success handling In order: Add reference to relevant section of USBTMC usb488 subclass specs. Print debug output of capabilities only when it was retrieved successfully. Clear return value on success, otherwise driver always reports failure. Signed-off-by: Gergely Imreh Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 6395f22a58e1..333ee02e7b2b 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -57,7 +57,9 @@ MODULE_DEVICE_TABLE(usb, usbtmc_devices); /* * This structure is the capabilities for the device - * See section 4.2.1.8 of the USBTMC specification for details. + * See section 4.2.1.8 of the USBTMC specification, + * and section 4.2.2 of the USBTMC usb488 subclass + * specification for details. */ struct usbtmc_dev_capabilities { __u8 interface_capabilities; @@ -796,20 +798,21 @@ static int get_capabilities(struct usbtmc_device_data *data) } dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); - dev_dbg(dev, "Interface capabilities are %x\n", buffer[4]); - dev_dbg(dev, "Device capabilities are %x\n", buffer[5]); - dev_dbg(dev, "USB488 interface capabilities are %x\n", buffer[14]); - dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); if (buffer[0] != USBTMC_STATUS_SUCCESS) { dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); rv = -EPERM; goto err_out; } + dev_dbg(dev, "Interface capabilities are %x\n", buffer[4]); + dev_dbg(dev, "Device capabilities are %x\n", buffer[5]); + dev_dbg(dev, "USB488 interface capabilities are %x\n", buffer[14]); + dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); data->capabilities.interface_capabilities = buffer[4]; data->capabilities.device_capabilities = buffer[5]; data->capabilities.usb488_interface_capabilities = buffer[14]; data->capabilities.usb488_device_capabilities = buffer[15]; + rv = 0; err_out: kfree(buffer); -- cgit v1.2.2