[PATCH evtest 8/9] Prevent out-of-bounds access for undefined types/codes

Peter Hutterer peter.hutterer at who-t.net
Wed Aug 21 20:46:53 PDT 2013


The various arrays that define the names are of the respective type size
(i.e. rel is of size REL_CNT, etc.). This means the size is encoded at
compile time, with no boundary checks at runtime for whether a type or
code exceeds those limits.

Wrap the accesses into those arrays into helper functions that check for the
maximum allowed sizes for types and for the respective event codes.

Reported-by: Stéphane Chatty <chatty at enac.fr>
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 evtest.c | 47 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/evtest.c b/evtest.c
index fd30774..3b2f7bb 100644
--- a/evtest.c
+++ b/evtest.c
@@ -167,6 +167,22 @@ static const char * const events[EV_MAX + 1] = {
 	NAME_ELEMENT(EV_FF_STATUS),		NAME_ELEMENT(EV_SW),
 };
 
+static const int maxval[EV_MAX + 1] = {
+	[0 ... EV_MAX] = -1,
+	[EV_SYN] = SYN_MAX,
+	[EV_KEY] = KEY_MAX,
+	[EV_REL] = REL_MAX,
+	[EV_ABS] = ABS_MAX,
+	[EV_MSC] = MSC_MAX,
+	[EV_SW] = SW_MAX,
+	[EV_LED] = LED_MAX,
+	[EV_SND] = SND_MAX,
+	[EV_REP] = REP_MAX,
+	[EV_FF] = FF_MAX,
+	[EV_FF_STATUS] = FF_STATUS_MAX,
+};
+
+
 #ifdef INPUT_PROP_SEMI_MT
 static const char * const props[INPUT_PROP_MAX + 1] = {
 	[0 ... INPUT_PROP_MAX] = NULL,
@@ -748,6 +764,21 @@ static void print_repdata(int fd)
 
 }
 
+static inline const char* typename(unsigned int type)
+{
+	return (type <= EV_MAX && events[type]) ? events[type] : "?";
+}
+
+static inline const char* codename(unsigned int type, unsigned int code)
+{
+	return (type <= EV_MAX && code <= maxval[type] && names[type] && names[type][code]) ? names[type][code] : "?";
+}
+
+static inline const char* propname(unsigned int prop)
+{
+	return (prop <= INPUT_PROP_MAX && props[prop]) ? props[prop] : "?";
+}
+
 /**
  * Print static device information (no events). This information includes
  * version numbers, device name and all bits supported by this device.
@@ -787,12 +818,12 @@ static int print_device_info(int fd)
 
 	for (type = 0; type < EV_MAX; type++) {
 		if (test_bit(type, bit[0]) && type != EV_REP) {
-			printf("  Event type %d (%s)\n", type, events[type] ? events[type] : "?");
+			printf("  Event type %d (%s)\n", type, typename(type));
 			if (type == EV_SYN) continue;
 			ioctl(fd, EVIOCGBIT(type, KEY_MAX), bit[type]);
 			for (code = 0; code < KEY_MAX; code++)
 				if (test_bit(code, bit[type])) {
-					printf("    Event code %d (%s)\n", code, names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
+					printf("    Event code %d (%s)\n", code, codename(type, code));
 					if (type == EV_ABS)
 						print_absdata(fd, code);
 				}
@@ -809,7 +840,7 @@ static int print_device_info(int fd)
 	}
 	for (prop = 0; prop < INPUT_PROP_MAX; prop++) {
 		if (test_bit(prop, propbits))
-			printf("  Property type %d (%s)\n", prop, props[prop] ? props[prop] : "?");
+			printf("  Property type %d (%s)\n", prop, propname(prop));
 	}
 #endif
 
@@ -846,15 +877,13 @@ static int print_events(int fd)
 
 			if (type == EV_SYN) {
 				if (code == SYN_MT_REPORT)
-					printf("++++++++++++++ %s ++++++++++++\n", syns[code]);
+					printf("++++++++++++++ %s ++++++++++++\n", codename(type, code));
 				else
-					printf("-------------- %s ------------\n", syns[code]);
+					printf("-------------- %s ------------\n", codename(type, code));
 			} else {
 				printf("type %d (%s), code %d (%s), ",
-					type,
-					events[type] ? events[type] : "?",
-					code,
-					names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
+					type, typename(type),
+					code, codename(type, code));
 				if (type == EV_MSC && (code == MSC_RAW || code == MSC_SCAN))
 					printf("value %02x\n", ev[i].value);
 				else
-- 
1.8.2.1



More information about the Input-tools mailing list