4ea5b52
From 0f8536022831faaba3a952fa633902d9686f535f Mon Sep 17 00:00:00 2001
4ea5b52
From: Vladis Dronov <vdronov@redhat.com>
4ea5b52
Date: Wed, 23 Mar 2016 15:53:07 -0400
4ea5b52
Subject: [PATCH] Input: ati_remote2: fix crashes on detecting device with
4ea5b52
 invalid descriptor
4ea5b52
4ea5b52
The ati_remote2 driver expects at least two interfaces with one
4ea5b52
endpoint each. If given malicious descriptor that specify one
4ea5b52
interface or no endpoints, it will crash in the probe function.
4ea5b52
Ensure there is at least two interfaces and one endpoint for each
4ea5b52
interface before using it.
4ea5b52
4ea5b52
The full disclosure: http://seclists.org/bugtraq/2016/Mar/90
4ea5b52
4ea5b52
Reported-by: Ralf Spenneberg <ralf@spenneberg.net>
4ea5b52
Signed-off-by: Vladis Dronov <vdronov@redhat.com>
4ea5b52
---
4ea5b52
 drivers/input/misc/ati_remote2.c | 36 ++++++++++++++++++++++++++++++------
4ea5b52
 1 file changed, 30 insertions(+), 6 deletions(-)
4ea5b52
4ea5b52
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
4ea5b52
index cfd58e87da26..cf5d1e8d92c7 100644
4ea5b52
--- a/drivers/input/misc/ati_remote2.c
4ea5b52
+++ b/drivers/input/misc/ati_remote2.c
4ea5b52
@@ -817,26 +817,49 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
4ea5b52
 
4ea5b52
 	ar2->udev = udev;
4ea5b52
 
4ea5b52
+	/* Sanity check, first interface must have an endpoint */
4ea5b52
+	if ((alt->desc.bNumEndpoints < 1) || !alt->endpoint) {
4ea5b52
+		dev_err(&interface->dev,
4ea5b52
+			"%s(): interface 0 must have an endpoint\n", __func__);
4ea5b52
+		r = -ENODEV;
4ea5b52
+		goto fail1;
4ea5b52
+	}
4ea5b52
 	ar2->intf[0] = interface;
4ea5b52
 	ar2->ep[0] = &alt->endpoint[0].desc;
4ea5b52
 
4ea5b52
+	/* Sanity check, the device must have two interfaces */
4ea5b52
 	ar2->intf[1] = usb_ifnum_to_if(udev, 1);
4ea5b52
+	if ((udev->actconfig->desc.bNumInterfaces < 2) || !ar2->intf[1]) {
4ea5b52
+		dev_err(&interface->dev, "%s(): need 2 interfaces, found %d\n",
4ea5b52
+			__func__, udev->actconfig->desc.bNumInterfaces);
4ea5b52
+		r = -ENODEV;
4ea5b52
+		goto fail1;
4ea5b52
+	}
4ea5b52
+
4ea5b52
 	r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2);
4ea5b52
 	if (r)
4ea5b52
 		goto fail1;
4ea5b52
+
4ea5b52
+	/* Sanity check, second interface must have an endpoint */
4ea5b52
 	alt = ar2->intf[1]->cur_altsetting;
4ea5b52
+	if ((alt->desc.bNumEndpoints < 1) || !alt->endpoint) {
4ea5b52
+		dev_err(&interface->dev,
4ea5b52
+			"%s(): interface 1 must have an endpoint\n", __func__);
4ea5b52
+		r = -ENODEV;
4ea5b52
+		goto fail2;
4ea5b52
+	}
4ea5b52
 	ar2->ep[1] = &alt->endpoint[0].desc;
4ea5b52
 
4ea5b52
 	r = ati_remote2_urb_init(ar2);
4ea5b52
 	if (r)
4ea5b52
-		goto fail2;
4ea5b52
+		goto fail3;
4ea5b52
 
4ea5b52
 	ar2->channel_mask = channel_mask;
4ea5b52
 	ar2->mode_mask = mode_mask;
4ea5b52
 
4ea5b52
 	r = ati_remote2_setup(ar2, ar2->channel_mask);
4ea5b52
 	if (r)
4ea5b52
-		goto fail2;
4ea5b52
+		goto fail3;
4ea5b52
 
4ea5b52
 	usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
4ea5b52
 	strlcat(ar2->phys, "/input0", sizeof(ar2->phys));
4ea5b52
@@ -845,11 +868,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
4ea5b52
 
4ea5b52
 	r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group);
4ea5b52
 	if (r)
4ea5b52
-		goto fail2;
4ea5b52
+		goto fail3;
4ea5b52
 
4ea5b52
 	r = ati_remote2_input_init(ar2);
4ea5b52
 	if (r)
4ea5b52
-		goto fail3;
4ea5b52
+		goto fail4;
4ea5b52
 
4ea5b52
 	usb_set_intfdata(interface, ar2);
4ea5b52
 
4ea5b52
@@ -857,10 +880,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
4ea5b52
 
4ea5b52
 	return 0;
4ea5b52
 
4ea5b52
- fail3:
4ea5b52
+ fail4:
4ea5b52
 	sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group);
4ea5b52
- fail2:
4ea5b52
+ fail3:
4ea5b52
 	ati_remote2_urb_cleanup(ar2);
4ea5b52
+ fail2:
4ea5b52
 	usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
4ea5b52
  fail1:
4ea5b52
 	kfree(ar2);
4ea5b52
-- 
4ea5b52
2.5.0
4ea5b52