1From 128c16a682034263eb519c89bc0934eeb6fa8cfa Mon Sep 17 00:00:00 2001
2From: Javier Martinez Canillas <javierm@redhat.com>
3Date: Fri, 11 Dec 2020 19:19:21 +0100
4Subject: [PATCH] usb: Avoid possible out-of-bound accesses caused by malicious
5 devices
6
7The maximum number of configurations and interfaces are fixed but there is
8no out-of-bound checking to prevent a malicious USB device to report large
9values for these and cause accesses outside the arrays' memory.
10
11Fixes: CVE-2020-25647
12
13Reported-by: Joseph Tartaro <joseph.tartaro@ioactive.com>
14Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
15Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
16Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
17Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
18---
19 grub-core/bus/usb/usb.c | 15 ++++++++++++---
20 include/grub/usb.h      | 10 +++++++---
21 2 files changed, 19 insertions(+), 6 deletions(-)
22
23diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c
24index 8da5e4c..7cb3cc2 100644
25--- a/grub-core/bus/usb/usb.c
26+++ b/grub-core/bus/usb/usb.c
27@@ -75,6 +75,9 @@ grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook,
28 grub_usb_err_t
29 grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
30 {
31+  if (endpoint >= GRUB_USB_MAX_TOGGLE)
32+    return GRUB_USB_ERR_BADDEVICE;
33+
34   dev->toggle[endpoint] = 0;
35   return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
36 				     | GRUB_USB_REQTYPE_STANDARD
37@@ -134,10 +137,10 @@ grub_usb_device_initialize (grub_usb_device_t dev)
38     return err;
39   descdev = &dev->descdev;
40
41-  for (i = 0; i < 8; i++)
42+  for (i = 0; i < GRUB_USB_MAX_CONF; i++)
43     dev->config[i].descconf = NULL;
44
45-  if (descdev->configcnt == 0)
46+  if (descdev->configcnt == 0 || descdev->configcnt > GRUB_USB_MAX_CONF)
47     {
48       err = GRUB_USB_ERR_BADDEVICE;
49       goto fail;
50@@ -172,6 +175,12 @@ grub_usb_device_initialize (grub_usb_device_t dev)
51       /* Skip the configuration descriptor.  */
52       pos = dev->config[i].descconf->length;
53
54+      if (dev->config[i].descconf->numif > GRUB_USB_MAX_IF)
55+        {
56+          err = GRUB_USB_ERR_BADDEVICE;
57+          goto fail;
58+        }
59+
60       /* Read all interfaces.  */
61       for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
62 	{
63@@ -217,7 +226,7 @@ grub_usb_device_initialize (grub_usb_device_t dev)
64
65  fail:
66
67-  for (i = 0; i < 8; i++)
68+  for (i = 0; i < GRUB_USB_MAX_CONF; i++)
69     grub_free (dev->config[i].descconf);
70
71   return err;
72diff --git a/include/grub/usb.h b/include/grub/usb.h
73index 512ae1d..6475c55 100644
74--- a/include/grub/usb.h
75+++ b/include/grub/usb.h
76@@ -23,6 +23,10 @@
77 #include <grub/usbdesc.h>
78 #include <grub/usbtrans.h>
79
80+#define GRUB_USB_MAX_CONF    8
81+#define GRUB_USB_MAX_IF      32
82+#define GRUB_USB_MAX_TOGGLE  256
83+
84 typedef struct grub_usb_device *grub_usb_device_t;
85 typedef struct grub_usb_controller *grub_usb_controller_t;
86 typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t;
87@@ -167,7 +171,7 @@ struct grub_usb_configuration
88   struct grub_usb_desc_config *descconf;
89
90   /* Interfaces associated to this configuration.  */
91-  struct grub_usb_interface interf[32];
92+  struct grub_usb_interface interf[GRUB_USB_MAX_IF];
93 };
94
95 struct grub_usb_hub_port
96@@ -191,7 +195,7 @@ struct grub_usb_device
97   struct grub_usb_controller controller;
98
99   /* Device configurations (after opening the device).  */
100-  struct grub_usb_configuration config[8];
101+  struct grub_usb_configuration config[GRUB_USB_MAX_CONF];
102
103   /* Device address.  */
104   int addr;
105@@ -203,7 +207,7 @@ struct grub_usb_device
106   int initialized;
107
108   /* Data toggle values (used for bulk transfers only).  */
109-  int toggle[256];
110+  int toggle[GRUB_USB_MAX_TOGGLE];
111
112   /* Used by libusb wrapper.  Schedulded for removal. */
113   void *data;
114--
1152.14.2
116
117