mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
103 lines
3.5 KiB
Diff
103 lines
3.5 KiB
Diff
From 786de92b3cb26012d3d0f00ee37adf14527f35c4 Mon Sep 17 00:00:00 2001
|
|
From: Alan Stern <stern@rowland.harvard.edu>
|
|
Date: Fri, 22 Sep 2017 11:56:49 -0400
|
|
Subject: [PATCH] USB: uas: fix bug in handling of alternate settings
|
|
|
|
The uas driver has a subtle bug in the way it handles alternate
|
|
settings. The uas_find_uas_alt_setting() routine returns an
|
|
altsetting value (the bAlternateSetting number in the descriptor), but
|
|
uas_use_uas_driver() then treats that value as an index to the
|
|
intf->altsetting array, which it isn't.
|
|
|
|
Normally this doesn't cause any problems because the various
|
|
alternate settings have bAlternateSetting values 0, 1, 2, ..., so the
|
|
value is equal to the index in the array. But this is not guaranteed,
|
|
and Andrey Konovalov used the syzkaller fuzzer with KASAN to get a
|
|
slab-out-of-bounds error by violating this assumption.
|
|
|
|
This patch fixes the bug by making uas_find_uas_alt_setting() return a
|
|
pointer to the altsetting entry rather than either the value or the
|
|
index. Pointers are less subject to misinterpretation.
|
|
|
|
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
|
|
Reported-by: Andrey Konovalov <andreyknvl@google.com>
|
|
Tested-by: Andrey Konovalov <andreyknvl@google.com>
|
|
CC: Oliver Neukum <oneukum@suse.com>
|
|
CC: <stable@vger.kernel.org>
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
---
|
|
drivers/usb/storage/uas-detect.h | 15 ++++++++-------
|
|
drivers/usb/storage/uas.c | 10 +++++-----
|
|
2 files changed, 13 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
|
|
index f58caa9e6a27e..a155cd02bce24 100644
|
|
--- a/drivers/usb/storage/uas-detect.h
|
|
+++ b/drivers/usb/storage/uas-detect.h
|
|
@@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_host_interface *intf)
|
|
intf->desc.bInterfaceProtocol == USB_PR_UAS);
|
|
}
|
|
|
|
-static int uas_find_uas_alt_setting(struct usb_interface *intf)
|
|
+static struct usb_host_interface *uas_find_uas_alt_setting(
|
|
+ struct usb_interface *intf)
|
|
{
|
|
int i;
|
|
|
|
@@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(struct usb_interface *intf)
|
|
struct usb_host_interface *alt = &intf->altsetting[i];
|
|
|
|
if (uas_is_interface(alt))
|
|
- return alt->desc.bAlternateSetting;
|
|
+ return alt;
|
|
}
|
|
|
|
- return -ENODEV;
|
|
+ return NULL;
|
|
}
|
|
|
|
static int uas_find_endpoints(struct usb_host_interface *alt,
|
|
@@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb_interface *intf,
|
|
struct usb_device *udev = interface_to_usbdev(intf);
|
|
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
|
unsigned long flags = id->driver_info;
|
|
- int r, alt;
|
|
-
|
|
+ struct usb_host_interface *alt;
|
|
+ int r;
|
|
|
|
alt = uas_find_uas_alt_setting(intf);
|
|
- if (alt < 0)
|
|
+ if (!alt)
|
|
return 0;
|
|
|
|
- r = uas_find_endpoints(&intf->altsetting[alt], eps);
|
|
+ r = uas_find_endpoints(alt, eps);
|
|
if (r < 0)
|
|
return 0;
|
|
|
|
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
|
|
index cfb1e3bbd4347..63cf981ed81cf 100644
|
|
--- a/drivers/usb/storage/uas.c
|
|
+++ b/drivers/usb/storage/uas.c
|
|
@@ -873,14 +873,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids);
|
|
static int uas_switch_interface(struct usb_device *udev,
|
|
struct usb_interface *intf)
|
|
{
|
|
- int alt;
|
|
+ struct usb_host_interface *alt;
|
|
|
|
alt = uas_find_uas_alt_setting(intf);
|
|
- if (alt < 0)
|
|
- return alt;
|
|
+ if (!alt)
|
|
+ return -ENODEV;
|
|
|
|
- return usb_set_interface(udev,
|
|
- intf->altsetting[0].desc.bInterfaceNumber, alt);
|
|
+ return usb_set_interface(udev, alt->desc.bInterfaceNumber,
|
|
+ alt->desc.bAlternateSetting);
|
|
}
|
|
|
|
static int uas_configure_endpoints(struct uas_dev_info *devinfo)
|