aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2012-04-26 15:59:10 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-07 11:56:36 -0400
commit197d1155b07b582d9969f456f61ee07d632af7e1 (patch)
tree54e9966a3010df457cfbbd0f44bfdc83d4b84e22
parentca288ca1de5957cb50e170dcdb5375c0e6467405 (diff)
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>
-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 76f061375e1..00b7bf9a20c 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)
108 spin_lock(&desc->iuspin); 108 spin_lock(&desc->iuspin);
109 desc->werr = urb->status; 109 desc->werr = urb->status;
110 spin_unlock(&desc->iuspin); 110 spin_unlock(&desc->iuspin);
111 clear_bit(WDM_IN_USE, &desc->flags);
112 kfree(desc->outbuf); 111 kfree(desc->outbuf);
112 desc->outbuf = NULL;
113 clear_bit(WDM_IN_USE, &desc->flags);
113 wake_up(&desc->wait); 114 wake_up(&desc->wait);
114} 115}
115 116
@@ -312,7 +313,7 @@ static ssize_t wdm_write
312 if (we < 0) 313 if (we < 0)
313 return -EIO; 314 return -EIO;
314 315
315 desc->outbuf = buf = kmalloc(count, GFP_KERNEL); 316 buf = kmalloc(count, GFP_KERNEL);
316 if (!buf) { 317 if (!buf) {
317 rv = -ENOMEM; 318 rv = -ENOMEM;
318 goto outnl; 319 goto outnl;
@@ -376,10 +377,12 @@ static ssize_t wdm_write
376 req->wIndex = desc->inum; 377 req->wIndex = desc->inum;
377 req->wLength = cpu_to_le16(count); 378 req->wLength = cpu_to_le16(count);
378 set_bit(WDM_IN_USE, &desc->flags); 379 set_bit(WDM_IN_USE, &desc->flags);
380 desc->outbuf = buf;
379 381
380 rv = usb_submit_urb(desc->command, GFP_KERNEL); 382 rv = usb_submit_urb(desc->command, GFP_KERNEL);
381 if (rv < 0) { 383 if (rv < 0) {
382 kfree(buf); 384 kfree(buf);
385 desc->outbuf = NULL;
383 clear_bit(WDM_IN_USE, &desc->flags); 386 clear_bit(WDM_IN_USE, &desc->flags);
384 dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); 387 dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
385 } else { 388 } else {