88590d8
From 10d98bced414c6fc1d09db123e7f762d91b5ebea Mon Sep 17 00:00:00 2001
88590d8
From: Johan Hovold <johan@kernel.org>
88590d8
Date: Wed, 23 Sep 2015 11:41:42 -0700
88590d8
Subject: [PATCH] USB: whiteheat: fix potential null-deref at probe
88590d8
88590d8
Fix potential null-pointer dereference at probe by making sure that the
88590d8
required endpoints are present.
88590d8
88590d8
The whiteheat driver assumes there are at least five pairs of bulk
88590d8
endpoints, of which the final pair is used for the "command port". An
88590d8
attempt to bind to an interface with fewer bulk endpoints would
88590d8
currently lead to an oops.
88590d8
88590d8
Fixes CVE-2015-5257.
88590d8
88590d8
Reported-by: Moein Ghasemzadeh <moein@istuary.com>
88590d8
Cc: stable <stable@vger.kernel.org>
88590d8
Signed-off-by: Johan Hovold <johan@kernel.org>
88590d8
---
88590d8
 drivers/usb/serial/whiteheat.c | 31 +++++++++++++++++++++++++++++++
88590d8
 1 file changed, 31 insertions(+)
88590d8
88590d8
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
88590d8
index 6c3734d2b45a..d3ea90bef84d 100644
88590d8
--- a/drivers/usb/serial/whiteheat.c
88590d8
+++ b/drivers/usb/serial/whiteheat.c
88590d8
@@ -80,6 +80,8 @@ static int  whiteheat_firmware_download(struct usb_serial *serial,
88590d8
 static int  whiteheat_firmware_attach(struct usb_serial *serial);
88590d8
 
88590d8
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
88590d8
+static int whiteheat_probe(struct usb_serial *serial,
88590d8
+				const struct usb_device_id *id);
88590d8
 static int  whiteheat_attach(struct usb_serial *serial);
88590d8
 static void whiteheat_release(struct usb_serial *serial);
88590d8
 static int  whiteheat_port_probe(struct usb_serial_port *port);
88590d8
@@ -116,6 +118,7 @@ static struct usb_serial_driver whiteheat_device = {
88590d8
 	.description =		"Connect Tech - WhiteHEAT",
88590d8
 	.id_table =		id_table_std,
88590d8
 	.num_ports =		4,
88590d8
+	.probe =		whiteheat_probe,
88590d8
 	.attach =		whiteheat_attach,
88590d8
 	.release =		whiteheat_release,
88590d8
 	.port_probe =		whiteheat_port_probe,
88590d8
@@ -217,6 +220,34 @@ static int whiteheat_firmware_attach(struct usb_serial *serial)
88590d8
 /*****************************************************************************
88590d8
  * Connect Tech's White Heat serial driver functions
88590d8
  *****************************************************************************/
88590d8
+
88590d8
+static int whiteheat_probe(struct usb_serial *serial,
88590d8
+				const struct usb_device_id *id)
88590d8
+{
88590d8
+	struct usb_host_interface *iface_desc;
88590d8
+	struct usb_endpoint_descriptor *endpoint;
88590d8
+	size_t num_bulk_in = 0;
88590d8
+	size_t num_bulk_out = 0;
88590d8
+	size_t min_num_bulk;
88590d8
+	unsigned int i;
88590d8
+
88590d8
+	iface_desc = serial->interface->cur_altsetting;
88590d8
+
88590d8
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
88590d8
+		endpoint = &iface_desc->endpoint[i].desc;
88590d8
+		if (usb_endpoint_is_bulk_in(endpoint))
88590d8
+			++num_bulk_in;
88590d8
+		if (usb_endpoint_is_bulk_out(endpoint))
88590d8
+			++num_bulk_out;
88590d8
+	}
88590d8
+
88590d8
+	min_num_bulk = COMMAND_PORT + 1;
88590d8
+	if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk)
88590d8
+		return -ENODEV;
88590d8
+
88590d8
+	return 0;
88590d8
+}
88590d8
+
88590d8
 static int whiteheat_attach(struct usb_serial *serial)
88590d8
 {
88590d8
 	struct usb_serial_port *command_port;
88590d8
-- 
88590d8
2.4.3
88590d8