diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2017-10-23 16:46:00 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-11-02 09:49:14 +0100 |
commit | 52f65e35c2b85908fa66cfc265be4e3fd88744a3 (patch) | |
tree | 1bf53ad0701f90f23315b2d66d4aec0f49cdd2b4 | |
parent | 9460dd36333445223d27c92df067eae2dcc49aa8 (diff) | |
download | linux-52f65e35c2b85908fa66cfc265be4e3fd88744a3.tar.gz linux-52f65e35c2b85908fa66cfc265be4e3fd88744a3.tar.bz2 linux-52f65e35c2b85908fa66cfc265be4e3fd88744a3.zip |
Input: gtco - fix potential out-of-bound access
commit a50829479f58416a013a4ccca791336af3c584c7 upstream.
parse_hid_report_descriptor() has a while (i < length) loop, which
only guarantees that there's at least 1 byte in the buffer, but the
loop body can read multiple bytes which causes out-of-bounds access.
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Reviewed-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/input/tablet/gtco.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index abf09ac42ce4..339a0e2d2f86 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -230,13 +230,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, /* Walk this report and pull out the info we need */ while (i < length) { - prefix = report[i]; - - /* Skip over prefix */ - i++; + prefix = report[i++]; /* Determine data size and save the data in the proper variable */ - size = PREF_SIZE(prefix); + size = (1U << PREF_SIZE(prefix)) >> 1; + if (i + size > length) { + dev_err(ddev, + "Not enough data (need %d, have %d)\n", + i + size, length); + break; + } + switch (size) { case 1: data = report[i]; @@ -244,8 +248,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, case 2: data16 = get_unaligned_le16(&report[i]); break; - case 3: - size = 4; + case 4: data32 = get_unaligned_le32(&report[i]); break; } |