aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2012-04-26 21:59:10 +0200
committerBen Hutchings <ben@decadent.org.uk>2012-05-11 13:14:41 +0100
commit670515c56290b7b7435f066e9bc0999fa1fc29b7 (patch)
tree1646e170519a62acefe85e91d540b964c30dee8d /drivers/usb/class
parent54f74773233a4ac43bd5149aa2cb1734da37506b (diff)
downloadkernel_samsung_smdk4412-670515c56290b7b7435f066e9bc0999fa1fc29b7.zip
kernel_samsung_smdk4412-670515c56290b7b7435f066e9bc0999fa1fc29b7.tar.gz
kernel_samsung_smdk4412-670515c56290b7b7435f066e9bc0999fa1fc29b7.tar.bz2
USB: cdc-wdm: fix race leading leading to memory corruption
commit 5c22837adca7c30b66121cf18ad3e160134268d4 upstream. This patch fixes a race whereby a pointer to a buffer would be overwritten while the buffer was in use leading to a double free and a memory leak. This causes crashes. This bug was introduced in 2.6.34 Signed-off-by: Oliver Neukum <oneukum@suse.de> Tested-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/cdc-wdm.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 9eb71d8..2db0327 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -108,8 +108,9 @@ static void wdm_out_callback(struct urb *urb)
spin_lock(&desc->iuspin);
desc->werr = urb->status;
spin_unlock(&desc->iuspin);
- clear_bit(WDM_IN_USE, &desc->flags);
kfree(desc->outbuf);
+ desc->outbuf = NULL;
+ clear_bit(WDM_IN_USE, &desc->flags);
wake_up(&desc->wait);
}
@@ -312,7 +313,7 @@ static ssize_t wdm_write
if (we < 0)
return -EIO;
- desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
+ buf = kmalloc(count, GFP_KERNEL);
if (!buf) {
rv = -ENOMEM;
goto outnl;
@@ -376,10 +377,12 @@ static ssize_t wdm_write
req->wIndex = desc->inum;
req->wLength = cpu_to_le16(count);
set_bit(WDM_IN_USE, &desc->flags);
+ desc->outbuf = buf;
rv = usb_submit_urb(desc->command, GFP_KERNEL);
if (rv < 0) {
kfree(buf);
+ desc->outbuf = NULL;
clear_bit(WDM_IN_USE, &desc->flags);
dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
} else {