CVE-2013-1860 usb: cdc-wdm buf overflow triggered by dev (rhbz 921970 922004)

This commit is contained in:
Josh Boyer 2013-03-15 07:53:08 -04:00
parent f7c0765d63
commit c47f090f17
2 changed files with 98 additions and 1 deletions

View File

@ -0,0 +1,88 @@
From c0f5ecee4e741667b2493c742b60b6218d40b3aa Mon Sep 17 00:00:00 2001
From: Oliver Neukum <oneukum@suse.de>
Date: Tue, 12 Mar 2013 14:52:42 +0100
Subject: [PATCH] USB: cdc-wdm: fix buffer overflow
The buffer for responses must not overflow.
If this would happen, set a flag, drop the data and return
an error after user space has read all remaining data.
Signed-off-by: Oliver Neukum <oliver@neukum.org>
CC: stable@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/class/cdc-wdm.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 5f0cb41..122d056 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
#define WDM_RESPONDING 7
#define WDM_SUSPENDING 8
#define WDM_RESETTING 9
+#define WDM_OVERFLOW 10
#define WDM_MAX 16
@@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *urb)
{
struct wdm_device *desc = urb->context;
int status = urb->status;
+ int length = urb->actual_length;
spin_lock(&desc->iuspin);
clear_bit(WDM_RESPONDING, &desc->flags);
@@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *urb)
}
desc->rerr = status;
- desc->reslength = urb->actual_length;
- memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
- desc->length += desc->reslength;
+ if (length + desc->length > desc->wMaxCommand) {
+ /* The buffer would overflow */
+ set_bit(WDM_OVERFLOW, &desc->flags);
+ } else {
+ /* we may already be in overflow */
+ if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
+ memmove(desc->ubuf + desc->length, desc->inbuf, length);
+ desc->length += length;
+ desc->reslength = length;
+ }
+ }
skip_error:
wake_up(&desc->wait);
@@ -435,6 +445,11 @@ retry:
rv = -ENODEV;
goto err;
}
+ if (test_bit(WDM_OVERFLOW, &desc->flags)) {
+ clear_bit(WDM_OVERFLOW, &desc->flags);
+ rv = -ENOBUFS;
+ goto err;
+ }
i++;
if (file->f_flags & O_NONBLOCK) {
if (!test_bit(WDM_READ, &desc->flags)) {
@@ -478,6 +493,7 @@ retry:
spin_unlock_irq(&desc->iuspin);
goto retry;
}
+
if (!desc->reslength) { /* zero length read */
dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
clear_bit(WDM_READ, &desc->flags);
@@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_interface *intf)
struct wdm_device *desc = wdm_find_device(intf);
int rv;
+ clear_bit(WDM_OVERFLOW, &desc->flags);
clear_bit(WDM_RESETTING, &desc->flags);
rv = recover_from_urb_loss(desc);
mutex_unlock(&desc->wlock);
--
1.8.1.2

View File

@ -62,7 +62,7 @@ Summary: The Linux kernel
# For non-released -rc kernels, this will be appended after the rcX and
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
#
%global baserelease 201
%global baserelease 202
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@ -793,6 +793,9 @@ Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch
#rhbz 859282
Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch
#CVE-2013-1860 rhbz 921970 922004
Patch24114: USB-cdc-wdm-fix-buffer-overflow.patch
#rhbz 920586
Patch25000: amd64_edac_fix_rank_count.patch
@ -1548,6 +1551,9 @@ ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch
#rhbz 859282
ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch
#CVE-2013-1860 rhbz 921970 922004
ApplyPatch USB-cdc-wdm-fix-buffer-overflow.patch
# END OF PATCH APPLICATIONS
%endif
@ -2405,6 +2411,9 @@ fi
# ||----w |
# || ||
%changelog
* Fri Mar 15 2013 Josh Boyer <jwboyer@redhat.com>
- CVE-2013-1860 usb: cdc-wdm buf overflow triggered by dev (rhbz 921970 922004)
* Thu Mar 14 2013 Justin M. Forbes <jforbes@redhat.com> 3.8.3-201
- Linux v3.8.3