lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20171128100426.306290757@linuxfoundation.org>
Date:   Tue, 28 Nov 2017 11:19:47 +0100
From:   Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To:     linux-kernel@...r.kernel.org
Cc:     Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        stable@...r.kernel.org, Oliver Neukum <oneukum@...e.com>
Subject: [PATCH 3.18 48/67] USB: fix buffer overflows with parsing CDC headers

3.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Oliver Neukum <oneukum@...e.com>

Parsing CDC headers a buffer overflow cannot just be prevented
by checking that the remainder of the buffer is longer than minimum
length. The size of the fields to be parsed must be figured in, too.

In newer kernels this issue has been fixed at a central location with

commit 2e1c42391ff2556387b3cb6308b24f6f65619feb
Author: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Date:   Thu Sep 21 16:58:48 2017 +0200

    USB: core: harden cdc_parse_cdc_header

on anything older the parsing had not been centralised, so a separate
fix for each driver is necessary.

Signed-off-by: Oliver Neukum <oneukum@...e.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
 drivers/net/usb/cdc_ether.c |    9 ++++++++-
 drivers/usb/class/cdc-acm.c |    2 +-
 drivers/usb/class/cdc-wdm.c |    2 ++
 3 files changed, 11 insertions(+), 2 deletions(-)

--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -171,6 +171,8 @@ int usbnet_generic_cdc_bind(struct usbne
 				dev_dbg(&intf->dev, "extra CDC header\n");
 				goto bad_desc;
 			}
+			if (len < sizeof(struct usb_cdc_header_desc))
+				break;
 			info->header = (void *) buf;
 			if (info->header->bLength != sizeof(*info->header)) {
 				dev_dbg(&intf->dev, "CDC header len %u\n",
@@ -184,6 +186,8 @@ int usbnet_generic_cdc_bind(struct usbne
 			 */
 			if (rndis) {
 				struct usb_cdc_acm_descriptor *acm;
+				if (len < sizeof(struct usb_cdc_acm_descriptor))
+					break;
 
 				acm = (void *) buf;
 				if (acm->bmCapabilities) {
@@ -200,6 +204,8 @@ int usbnet_generic_cdc_bind(struct usbne
 				dev_dbg(&intf->dev, "extra CDC union\n");
 				goto bad_desc;
 			}
+			if (len < sizeof(struct usb_cdc_union_desc))
+				break;
 			info->u = (void *) buf;
 			if (info->u->bLength != sizeof(*info->u)) {
 				dev_dbg(&intf->dev, "CDC union len %u\n",
@@ -258,6 +264,8 @@ int usbnet_generic_cdc_bind(struct usbne
 				dev_dbg(&intf->dev, "extra CDC ether\n");
 				goto bad_desc;
 			}
+			if (len < sizeof(struct usb_cdc_ether_desc))
+				break;
 			info->ether = (void *) buf;
 			if (info->ether->bLength != sizeof(*info->ether)) {
 				dev_dbg(&intf->dev, "CDC ether len %u\n",
@@ -275,7 +283,6 @@ int usbnet_generic_cdc_bind(struct usbne
 				dev_dbg(&intf->dev, "extra MDLM descriptor\n");
 				goto bad_desc;
 			}
-
 			desc = (void *)buf;
 
 			if (desc->bLength != sizeof(*desc))
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1139,7 +1139,7 @@ static int acm_probe(struct usb_interfac
 		}
 	}
 
-	while (buflen > 0) {
+	while (buflen >= 3) { /* minimum length making sense */
 		elength = buffer[0];
 		if (!elength) {
 			dev_err(&intf->dev, "skipping garbage byte\n");
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -891,6 +891,8 @@ static int wdm_probe(struct usb_interfac
 		case USB_CDC_HEADER_TYPE:
 			break;
 		case USB_CDC_DMM_TYPE:
+			if (buflen < sizeof(struct usb_cdc_dmm_desc))
+				break;
 			dmhd = (struct usb_cdc_dmm_desc *)buffer;
 			maxcom = le16_to_cpu(dmhd->wMaxCommand);
 			dev_dbg(&intf->dev,


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ