diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-16 16:55:39 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-16 16:55:39 -0800 |
commit | 18688218d171cb653cbe82d03f72e51b02a5a83e (patch) | |
tree | c146673138876a9491853ca6618f2303895e943d /drivers/usb/core/devio.c | |
parent | 1ed10aa8e9e55e7f7b3374e532f453c4d0f5fe8a (diff) | |
parent | 31e5d4abceaa3d11ff583ddf76ec292e90eacb7d (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6:
USB: gadget: fix EEM gadget CRC usage
USB: otg Kconfig: let USB_OTG_UTILS select USB_ULPI option
USB: g_multi: fix CONFIG_USB_G_MULTI_RNDIS usage
kfifo: Don't use integer as NULL pointer
USB: FHCI: Fix build after kfifo rework
kfifo: Make kfifo_initialized work after kfifo_free
USB: serial: add usbid for dell wwan card to sierra.c
USB: SIS USB2VGA DRIVER: support KAIREN's USB VGA adaptor USB20SVGA-MB-PLUS
USB: ehci: phy low power mode bug fixing
USB: s3c-hsotg: Export usb_gadget_register_driver()
USB: r8a66597-udc: Prototype IS_ERR() and PTR_ERR()
USB: ftdi_sio: add device IDs (several ELV, one Mindstorms NXT)
USB: storage: Remove unneeded SC/PR from unusual_devs.h
USB: ftdi_sio: new device id for papouch AD4USB
USB: usbfs: properly clean up the as structure on error paths
USB: usbfs: only copy the actual data received
Diffstat (limited to 'drivers/usb/core/devio.c')
-rw-r--r-- | drivers/usb/core/devio.c | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6e8bcdfd23b..a678186f218 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1312,9 +1312,9 @@ static int processcompl(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer) + if (as->userbuffer && urb->actual_length) if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->transfer_buffer_length)) + urb->actual_length)) goto err_out; if (put_user(as->status, &userurb->status)) goto err_out; @@ -1334,14 +1334,11 @@ static int processcompl(struct async *as, void __user * __user *arg) } } - free_async(as); - if (put_user(addr, (void __user * __user *)arg)) return -EFAULT; return 0; err_out: - free_async(as); return -EFAULT; } @@ -1371,8 +1368,11 @@ static struct async *reap_as(struct dev_state *ps) static int proc_reapurb(struct dev_state *ps, void __user *arg) { struct async *as = reap_as(ps); - if (as) - return processcompl(as, (void __user * __user *)arg); + if (as) { + int retval = processcompl(as, (void __user * __user *)arg); + free_async(as); + return retval; + } if (signal_pending(current)) return -EINTR; return -EIO; @@ -1380,11 +1380,16 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg) static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) { + int retval; struct async *as; - if (!(as = async_getcompleted(ps))) - return -EAGAIN; - return processcompl(as, (void __user * __user *)arg); + as = async_getcompleted(ps); + retval = -EAGAIN; + if (as) { + retval = processcompl(as, (void __user * __user *)arg); + free_async(as); + } + return retval; } #ifdef CONFIG_COMPAT @@ -1475,9 +1480,9 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer) + if (as->userbuffer && urb->actual_length) if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->transfer_buffer_length)) + urb->actual_length)) return -EFAULT; if (put_user(as->status, &userurb->status)) return -EFAULT; @@ -1497,7 +1502,6 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) } } - free_async(as); if (put_user(ptr_to_compat(addr), (u32 __user *)arg)) return -EFAULT; return 0; @@ -1506,8 +1510,11 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) { struct async *as = reap_as(ps); - if (as) - return processcompl_compat(as, (void __user * __user *)arg); + if (as) { + int retval = processcompl_compat(as, (void __user * __user *)arg); + free_async(as); + return retval; + } if (signal_pending(current)) return -EINTR; return -EIO; @@ -1515,11 +1522,16 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) { + int retval; struct async *as; - if (!(as = async_getcompleted(ps))) - return -EAGAIN; - return processcompl_compat(as, (void __user * __user *)arg); + retval = -EAGAIN; + as = async_getcompleted(ps); + if (as) { + retval = processcompl_compat(as, (void __user * __user *)arg); + free_async(as); + } + return retval; } |