| From 5c22837adca7c30b66121cf18ad3e160134268d4 Mon Sep 17 00:00:00 2001 |
| From: Oliver Neukum <oliver@neukum.org> |
| Date: Thu, 26 Apr 2012 21:59:10 +0200 |
| Subject: USB: cdc-wdm: fix race leading leading to memory corruption |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Oliver Neukum <oliver@neukum.org> |
| |
| 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> |
| |
| --- |
| drivers/usb/class/cdc-wdm.c | 7 +++++-- |
| 1 file changed, 5 insertions(+), 2 deletions(-) |
| |
| --- 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 |
| 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 { |