Input: gtco - bounds check collection indent level
authorGrant Hernandez <granthernandez@google.com>
Sat, 13 Jul 2019 08:00:12 +0000 (01:00 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 26 Jul 2019 07:14:21 +0000 (09:14 +0200)
commit 2a017fd82c5402b3c8df5e3d6e5165d9e6147dc1 upstream.

The GTCO tablet input driver configures itself from an HID report sent
via USB during the initial enumeration process. Some debugging messages
are generated during the parsing. A debugging message indentation
counter is not bounds checked, leading to the ability for a specially
crafted HID report to cause '-' and null bytes be written past the end
of the indentation array. As long as the kernel has CONFIG_DYNAMIC_DEBUG
enabled, this code will not be optimized out.  This was discovered
during code review after a previous syzkaller bug was found in this
driver.

Signed-off-by: Grant Hernandez <granthernandez@google.com>
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/input/tablet/gtco.c

index 4b8b9d7..3503122 100644 (file)
@@ -78,6 +78,7 @@ Scott Hill shill@gtcocalcomp.com
 
 /* Max size of a single report */
 #define REPORT_MAX_SIZE       10
+#define MAX_COLLECTION_LEVELS  10
 
 
 /* Bitmask whether pen is in range */
@@ -223,8 +224,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
        char  maintype = 'x';
        char  globtype[12];
        int   indent = 0;
-       char  indentstr[10] = "";
-
+       char  indentstr[MAX_COLLECTION_LEVELS + 1] = { 0 };
 
        dev_dbg(ddev, "======>>>>>>PARSE<<<<<<======\n");
 
@@ -350,6 +350,13 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
                        case TAG_MAIN_COL_START:
                                maintype = 'S';
 
+                               if (indent == MAX_COLLECTION_LEVELS) {
+                                       dev_err(ddev, "Collection level %d would exceed limit of %d\n",
+                                               indent + 1,
+                                               MAX_COLLECTION_LEVELS);
+                                       break;
+                               }
+
                                if (data == 0) {
                                        dev_dbg(ddev, "======>>>>>> Physical\n");
                                        strcpy(globtype, "Physical");
@@ -369,8 +376,15 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
                                break;
 
                        case TAG_MAIN_COL_END:
-                               dev_dbg(ddev, "<<<<<<======\n");
                                maintype = 'E';
+
+                               if (indent == 0) {
+                                       dev_err(ddev, "Collection level already at zero\n");
+                                       break;
+                               }
+
+                               dev_dbg(ddev, "<<<<<<======\n");
+
                                indent--;
                                for (x = 0; x < indent; x++)
                                        indentstr[x] = '-';