From 438957f8d4a84daa7fa5be6978ad5897a2e9e5e5 Mon Sep 17 00:00:00 2001 From: Bart Westgeest Date: Tue, 1 Nov 2011 15:01:28 -0400 Subject: staging: usbip: bugfix for deadlock Interrupts must be disabled prior to calling usb_hcd_unlink_urb_from_ep. If interrupts are not disabled, it can potentially lead to a deadlock. The deadlock is readily reproduceable on a slower (ARM based) device such as the TI Pandaboard. Signed-off-by: Bart Westgeest Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_rx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 09c44abb89e8..3872b8cccdcf 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -68,6 +68,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, { struct usbip_device *ud = &vdev->ud; struct urb *urb; + unsigned long flags; spin_lock(&vdev->priv_lock); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); @@ -101,9 +102,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, usbip_dbg_vhci_rx("now giveback urb %p\n", urb); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -141,6 +142,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, { struct vhci_unlink *unlink; struct urb *urb; + unsigned long flags; usbip_dump_header(pdu); @@ -170,9 +172,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, urb->status = pdu->u.ret_unlink.status; pr_info("urb->status %d\n", urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); -- cgit v1.2.2 From f7364ba04b0961f3a1f978bbe77102606801e35f Mon Sep 17 00:00:00 2001 From: wwang Date: Mon, 31 Oct 2011 15:02:53 +0800 Subject: staging:rts_pstor:Complete scanning_done variable Complete scanning_done variable if rtsx-scan thread created failed. Signed-off-by: wwang Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts_pstor/rtsx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c index 480b0ed2e4de..115635f95024 100644 --- a/drivers/staging/rts_pstor/rtsx.c +++ b/drivers/staging/rts_pstor/rtsx.c @@ -1021,6 +1021,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan"); if (IS_ERR(th)) { printk(KERN_ERR "Unable to start the device-scanning thread\n"); + complete(&dev->scanning_done); quiesce_and_remove_host(dev); err = PTR_ERR(th); goto errout; -- cgit v1.2.2 From 8b78607fc4a26c2e26c4a614ff0bbd3380abc402 Mon Sep 17 00:00:00 2001 From: Bernd Porr Date: Tue, 8 Nov 2011 21:21:37 +0000 Subject: staging: comedi: usbduxsigma: Fixed wrong range for the analogue channel. It's actually +/-2.65V/2 and not +/-2.65V. Signed-off-by: Bernd Porr Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index a8fea9a91733..6144afb8cbaa 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1,4 +1,4 @@ -#define DRIVER_VERSION "v0.5" +#define DRIVER_VERSION "v0.6" #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" #define DRIVER_DESC "Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com" /* @@ -25,7 +25,7 @@ Driver: usbduxsigma Description: University of Stirling USB DAQ & INCITE Technology Limited Devices: [ITL] USB-DUX (usbduxsigma.o) Author: Bernd Porr -Updated: 21 Jul 2011 +Updated: 8 Nov 2011 Status: testing */ /* @@ -44,6 +44,7 @@ Status: testing * 0.3: proper vendor ID and driver name * 0.4: fixed D/A voltage range * 0.5: various bug fixes, health check at startup + * 0.6: corrected wrong input range */ /* generates loads of debug info */ @@ -175,7 +176,7 @@ Status: testing /* comedi constants */ static const struct comedi_lrange range_usbdux_ai_range = { 1, { BIP_RANGE - (2.65) + (2.65/2.0) } }; -- cgit v1.2.2 From 3ffab428f40849ed5f21bcfd7285bdef7902f9ca Mon Sep 17 00:00:00 2001 From: Bernd Porr Date: Tue, 8 Nov 2011 21:23:03 +0000 Subject: staging: comedi: fix oops for USB DAQ devices. This fixes kernel oops when an USB DAQ device is plugged out while it's communicating with the userspace software. Signed-off-by: Bernd Porr Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 71 +++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 21d8c1c16cd8..156622a6f162 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1452,9 +1452,6 @@ static struct vm_operations_struct comedi_vm_ops = { static int comedi_mmap(struct file *file, struct vm_area_struct *vma) { const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_async *async = NULL; unsigned long start = vma->vm_start; unsigned long size; @@ -1462,6 +1459,15 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) int i; int retval; struct comedi_subdevice *s; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + + dev_file_info = comedi_get_device_file_info(minor); + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1528,11 +1534,17 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_subdevice *read_subdev; struct comedi_subdevice *write_subdev; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1578,9 +1590,15 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1683,9 +1701,15 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1885,11 +1909,17 @@ ok: static int comedi_close(struct inode *inode, struct file *file) { const unsigned minor = iminor(inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_subdevice *s = NULL; int i; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); @@ -1923,10 +1953,15 @@ static int comedi_close(struct inode *inode, struct file *file) static int comedi_fasync(int fd, struct file *file, int on) { const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; return fasync_helper(fd, file, on, &dev->async_queue); } -- cgit v1.2.2 From df30b21cb0eed5ba8a8e0cdfeebc66ba8cde821d Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Sat, 29 Oct 2011 09:45:39 +0200 Subject: Staging: comedi: fix mmap_count In comedi_fops, mmap_count is decremented at comedi_vm_ops->close but it is not incremented at comedi_vm_ops->open. This may result in a negative counter. The patch introduces the open method to keep the counter consistent. The bug was triggerd by this sample code: mmap(0, ...., comedi_fd); fork(); exit(0); Acked-by: Alessandro Rubini Signed-off-by: Federico Vaga Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 156622a6f162..88caa7376999 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1432,7 +1432,21 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return ret; } -static void comedi_unmap(struct vm_area_struct *area) + +static void comedi_vm_open(struct vm_area_struct *area) +{ + struct comedi_async *async; + struct comedi_device *dev; + + async = area->vm_private_data; + dev = async->subdevice->device; + + mutex_lock(&dev->mutex); + async->mmap_count++; + mutex_unlock(&dev->mutex); +} + +static void comedi_vm_close(struct vm_area_struct *area) { struct comedi_async *async; struct comedi_device *dev; @@ -1446,7 +1460,8 @@ static void comedi_unmap(struct vm_area_struct *area) } static struct vm_operations_struct comedi_vm_ops = { - .close = comedi_unmap, + .open = comedi_vm_open, + .close = comedi_vm_close, }; static int comedi_mmap(struct file *file, struct vm_area_struct *vma) -- cgit v1.2.2 From 6a9ce6b654e491981f6ef7e214cbd4f63e033848 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Sat, 29 Oct 2011 09:47:39 +0200 Subject: Staging: comedi: fix signal handling in read and write After sleeping on a wait queue, signal_pending(current) should be checked (not before sleeping). Acked-by: Alessandro Rubini Signed-off-by: Federico Vaga Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 88caa7376999..ebdcecda3583 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1673,11 +1673,11 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, retval = -EAGAIN; break; } + schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } - schedule(); if (!s->busy) break; if (s->busy != file) { @@ -1780,11 +1780,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, retval = -EAGAIN; break; } + schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } - schedule(); if (!s->busy) { retval = 0; break; -- cgit v1.2.2 From e384a41141949843899affcf51f4e6e646c1fe9f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 4 Nov 2011 21:20:43 +0300 Subject: Staging: comedi: integer overflow in do_insnlist_ioctl() There is an integer overflow here that could cause memory corruption on 32 bit systems. insnlist.n_insns could be a very high value size calculation for kmalloc() could overflow resulting in a smaller "insns" than expected. In the for (i = 0; i < insnlist.n_insns; i++) {... loop we would read past the end of the buffer, possibly corrupting memory as well. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index ebdcecda3583..ed4853f194c4 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -670,6 +670,11 @@ static int do_insnlist_ioctl(struct comedi_device *dev, goto error; } + if (sizeof(struct comedi_insn) * insnlist.n_insns < insnlist.n_insns) { + ret = -EINVAL; + goto error; + } + insns = kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); if (!insns) { -- cgit v1.2.2 From 06b446c8af5db5a98b2eaa30b513c79089ed254b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 28 Nov 2011 04:34:34 +0900 Subject: Revert "Staging: comedi: integer overflow in do_insnlist_ioctl()" This reverts commit e384a41141949843899affcf51f4e6e646c1fe9f. It's not the correct way to solve this issue. Acked-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index ed4853f194c4..ebdcecda3583 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -670,11 +670,6 @@ static int do_insnlist_ioctl(struct comedi_device *dev, goto error; } - if (sizeof(struct comedi_insn) * insnlist.n_insns < insnlist.n_insns) { - ret = -EINVAL; - goto error; - } - insns = kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); if (!insns) { -- cgit v1.2.2 From dfd8ee92a9192d78aa38cf8699df3630a7c88c85 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Fri, 25 Nov 2011 16:46:51 -0500 Subject: Staging: comedi: fix integer overflow in do_insnlist_ioctl() There is a potential integer overflow in do_insnlist_ioctl() if userspace passes in a large insnlist.n_insns. The call to kmalloc() would allocate a small buffer, leading to a memory corruption. The bug was reported by Dan Carpenter and Haogang Chen . The patch was suggested by Ian Abbott and Lars-Peter Clausen . Reported-by: Dan Carpenter Reported-by: Haogang Chen . Cc: Ian Abbott Cc: Lars-Peter Clausen Signed-off-by: Xi Wang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index ebdcecda3583..5e78c77d5a08 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -671,7 +671,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev, } insns = - kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); + kcalloc(insnlist.n_insns, sizeof(struct comedi_insn), GFP_KERNEL); if (!insns) { DPRINTK("kmalloc failed\n"); ret = -ENOMEM; -- cgit v1.2.2