diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2017-10-23 19:46:00 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2017-10-27 18:14:41 -0400 |
commit | a50829479f58416a013a4ccca791336af3c584c7 (patch) | |
tree | 74da0be0913dcd747df260a8432f2d8d8c708607 | |
parent | 57a95b41869b8f0d1949c24df2a9dac1ca7082ee (diff) |
Input: gtco - fix potential out-of-bound access
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>
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-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 b796e891e2ee..4b8b9d7aa75e 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, | |||
230 | 230 | ||
231 | /* Walk this report and pull out the info we need */ | 231 | /* Walk this report and pull out the info we need */ |
232 | while (i < length) { | 232 | while (i < length) { |
233 | prefix = report[i]; | 233 | prefix = report[i++]; |
234 | |||
235 | /* Skip over prefix */ | ||
236 | i++; | ||
237 | 234 | ||
238 | /* Determine data size and save the data in the proper variable */ | 235 | /* Determine data size and save the data in the proper variable */ |
239 | size = PREF_SIZE(prefix); | 236 | size = (1U << PREF_SIZE(prefix)) >> 1; |
237 | if (i + size > length) { | ||
238 | dev_err(ddev, | ||
239 | "Not enough data (need %d, have %d)\n", | ||
240 | i + size, length); | ||
241 | break; | ||
242 | } | ||
243 | |||
240 | switch (size) { | 244 | switch (size) { |
241 | case 1: | 245 | case 1: |
242 | data = report[i]; | 246 | data = report[i]; |
@@ -244,8 +248,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, | |||
244 | case 2: | 248 | case 2: |
245 | data16 = get_unaligned_le16(&report[i]); | 249 | data16 = get_unaligned_le16(&report[i]); |
246 | break; | 250 | break; |
247 | case 3: | 251 | case 4: |
248 | size = 4; | ||
249 | data32 = get_unaligned_le32(&report[i]); | 252 | data32 = get_unaligned_le32(&report[i]); |
250 | break; | 253 | break; |
251 | } | 254 | } |