Blame SOURCES/0070-evdev-decode-struct-input_absinfo-regardless-of-in-k.patch

86f512
From 5680918c9e2cc8b2418a3809892532be0d10018a Mon Sep 17 00:00:00 2001
86f512
From: Eugene Syromyatnikov <evgsyr@gmail.com>
86f512
Date: Thu, 17 Oct 2019 15:29:50 +0200
86f512
Subject: [PATCH 70/76] evdev: decode struct input_absinfo regardless of
86f512
 in-kernel definitions
86f512
86f512
* evdev.c (struct_input_absinfo): New typedef.
86f512
(abs_ioctl): Add code argument. Add orig_sz, res_sz, sz, read_sz local
86f512
variables. Decode resolution field regardless of
86f512
HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION.
86f512
(evdev_read_ioctl, evdev_write_ioctl): Pass code to abs_ioctl.
86f512
* tests/ioctl_evdev-success.c (print_input_absinfo): Update expected
86f512
output.
86f512
(main): Add absinfo_sz, absinfo_24, absinfo_32 local variables; add
86f512
additional checks for struct input_absinfo.
86f512
86f512
References: https://bugzilla.redhat.com/show_bug.cgi?id=1758201
86f512
---
86f512
 evdev.c                     | 78 ++++++++++++++++++++++++++++++---------------
86f512
 tests/ioctl_evdev-success.c | 51 ++++++++++++++++++++++++++---
86f512
 2 files changed, 99 insertions(+), 30 deletions(-)
86f512
86f512
Index: strace-5.1/evdev.c
86f512
===================================================================
86f512
--- strace-5.1.orig/evdev.c	2020-01-29 12:37:35.139765850 +0100
86f512
+++ strace-5.1/evdev.c	2020-01-29 12:39:10.344891943 +0100
86f512
@@ -37,6 +37,15 @@
86f512
 #  define SYN_MAX 0xf
86f512
 # endif
86f512
 
86f512
+typedef struct {
86f512
+	int32_t value;
86f512
+	int32_t minimum;
86f512
+	int32_t maximum;
86f512
+	int32_t fuzz;
86f512
+	int32_t flat;
86f512
+	int32_t resolution; /**< Added by Linux commit v2.6.31-rc1~100^2~1 */
86f512
+} struct_input_absinfo;
86f512
+
86f512
 /** Added by Linux commit v2.6.37-rc1~5^2~3^2~47 */
86f512
 typedef struct {
86f512
 	uint8_t  flags;
86f512
@@ -53,6 +62,9 @@
86f512
 	uint64_t codes_ptr;
86f512
 } struct_input_mask;
86f512
 
86f512
+static_assert(sizeof(struct input_absinfo) <= sizeof(struct_input_absinfo),
86f512
+	      "Unexpected struct input_absinfo size, please update "
86f512
+	      "the decoder");
86f512
 # ifdef HAVE_STRUCT_INPUT_KEYMAP_ENTRY
86f512
 static_assert(sizeof(struct input_keymap_entry)
86f512
 	      == sizeof(struct_input_keymap_entry),
86f512
@@ -85,36 +97,50 @@
86f512
 const size_t evdev_abs_size = ARRAY_SIZE(evdev_abs) - 1;
86f512
 
86f512
 static int
86f512
-abs_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
86f512
+abs_ioctl(struct tcb *const tcp, const unsigned int code,
86f512
+	  const kernel_ulong_t arg)
86f512
 {
86f512
+	static const size_t orig_sz = offsetofend(struct_input_absinfo, flat);
86f512
+	static const size_t res_sz = offsetofend(struct_input_absinfo,
86f512
+						 resolution);
86f512
+
86f512
+	struct_input_absinfo absinfo;
86f512
+	size_t sz = _IOC_SIZE(code);
86f512
+	size_t read_sz = MIN(sz, sizeof(absinfo));
86f512
+
86f512
+	if (sz < orig_sz)
86f512
+		return RVAL_DECODED;
86f512
+
86f512
 	tprints(", ");
86f512
 
86f512
-	struct input_absinfo absinfo;
86f512
+	if (umoven_or_printaddr(tcp, arg, read_sz, &absinfo))
86f512
+		return RVAL_IOCTL_DECODED;
86f512
 
86f512
-	if (!umove_or_printaddr(tcp, arg, &absinfo)) {
86f512
-		tprintf("{value=%u"
86f512
-			", minimum=%u, ",
86f512
-			absinfo.value,
86f512
-			absinfo.minimum);
86f512
-
86f512
-		if (!abbrev(tcp)) {
86f512
-			tprintf("maximum=%u"
86f512
-				", fuzz=%u"
86f512
-				", flat=%u",
86f512
-				absinfo.maximum,
86f512
-				absinfo.fuzz,
86f512
-				absinfo.flat);
86f512
-# ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
86f512
-			tprintf(", resolution=%u",
86f512
-				absinfo.resolution);
86f512
-# endif
86f512
-		} else {
86f512
-			tprints("...");
86f512
-		}
86f512
+	tprintf("{value=%u"
86f512
+		", minimum=%u, ",
86f512
+		absinfo.value,
86f512
+		absinfo.minimum);
86f512
 
86f512
-		tprints("}");
86f512
+	if (!abbrev(tcp)) {
86f512
+		tprintf("maximum=%u"
86f512
+			", fuzz=%u"
86f512
+			", flat=%u",
86f512
+			absinfo.maximum,
86f512
+			absinfo.fuzz,
86f512
+			absinfo.flat);
86f512
+		if (sz >= res_sz) {
86f512
+			tprintf(", resolution=%u%s",
86f512
+				absinfo.resolution,
86f512
+				sz > res_sz ? ", ..." : "");
86f512
+		} else if (sz > orig_sz) {
86f512
+			tprints(", ...");
86f512
+		}
86f512
+	} else {
86f512
+		tprints("...");
86f512
 	}
86f512
 
86f512
+	tprints("}");
86f512
+
86f512
 	return RVAL_IOCTL_DECODED;
86f512
 }
86f512
 
86f512
@@ -394,7 +420,7 @@
86f512
 
86f512
 	/* multi-number fixed-length commands */
86f512
 	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
86f512
-		return abs_ioctl(tcp, arg);
86f512
+		return abs_ioctl(tcp, code, arg);
86f512
 
86f512
 	/* multi-number variable-length commands */
86f512
 	if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
86f512
@@ -435,7 +461,7 @@
86f512
 
86f512
 	/* multi-number fixed-length commands */
86f512
 	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0)))
86f512
-		return abs_ioctl(tcp, arg);
86f512
+		return abs_ioctl(tcp, code, arg);
86f512
 
86f512
 	return 0;
86f512
 }
86f512
Index: strace-5.1/tests/ioctl_evdev-success.c
86f512
===================================================================
86f512
--- strace-5.1.orig/tests/ioctl_evdev-success.c	2020-01-27 19:35:30.929507199 +0100
86f512
+++ strace-5.1/tests/ioctl_evdev-success.c	2020-01-29 12:39:10.345891934 +0100
86f512
@@ -56,6 +56,9 @@
86f512
 print_input_absinfo(long rc, const void *ptr, const void *arg)
86f512
 {
86f512
 	const struct input_absinfo *absinfo = ptr;
86f512
+# if VERBOSE
86f512
+	const uintptr_t sz = (uintptr_t) arg;
86f512
+# endif
86f512
 
86f512
 	if (rc < 0) {
86f512
 		printf("%p", absinfo);
86f512
@@ -67,9 +70,20 @@
86f512
 	PRINT_FIELD_U(", ", *absinfo, maximum);
86f512
 	PRINT_FIELD_U(", ", *absinfo, fuzz);
86f512
 	PRINT_FIELD_U(", ", *absinfo, flat);
86f512
+	if (sz > offsetofend(struct input_absinfo, flat)) {
86f512
+		if (sz >= 24) {
86f512
 #  ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
86f512
-	PRINT_FIELD_U(", ", *absinfo, resolution);
86f512
+			PRINT_FIELD_U(", ", *absinfo, resolution);
86f512
+#  else
86f512
+			printf(", resolution=%u", *((int *) ptr + 5));
86f512
 #  endif
86f512
+
86f512
+			if (sz > 24)
86f512
+				printf(", ...");
86f512
+		} else {
86f512
+			printf(", ...");
86f512
+		}
86f512
+	}
86f512
 # else
86f512
 	printf(", ...");
86f512
 # endif
86f512
@@ -176,10 +190,22 @@
86f512
 				   ", EVIOCGID, NULL) returning %lu",
86f512
 				   inject_retval);
86f512
 
86f512
+	static const void *absinfo_sz =
86f512
+		(const void *) (uintptr_t) sizeof(struct input_absinfo);
86f512
+
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_id, id);
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_absinfo, absinfo);
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(int, bad_addr_slot);
86f512
 
86f512
+	struct input_absinfo *absinfo_24 = tail_alloc(MAX(sizeof(*absinfo_24),
86f512
+							  24));
86f512
+	struct input_absinfo *absinfo_32 = tail_alloc(MAX(sizeof(*absinfo_32),
86f512
+							  32));
86f512
+
86f512
+	fill_memory(absinfo, sizeof(struct input_absinfo));
86f512
+	fill_memory(absinfo_24, 24);
86f512
+	fill_memory(absinfo_32, 32);
86f512
+
86f512
 # ifdef EVIOCGMTSLOTS
86f512
 	int mtslots[] = { ABS_MT_SLOT, 1, 3 };
86f512
 	/* we use the second element to indicate the number of values */
86f512
@@ -236,9 +262,26 @@
86f512
 		const void *ptr;
86f512
 	} a[] = {
86f512
 		{ { ARG_STR(EVIOCGID), id, print_input_id }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 19), "EVIOCGABS(ABS_Y)",
86f512
+		    absinfo, NULL }, NULL },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 20),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 20 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 21),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_24, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 21 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 24),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_24, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 24 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 32),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_32, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 32 },
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz},
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz },
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz },
86f512
 		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_more, print_getbit },
86f512
 			inject_retval * 8 <= EV_LED
86f512
 				? (const void *) &ev_more_str_2
86f512
Index: strace-5.1/tests-m32/ioctl_evdev-success.c
86f512
===================================================================
86f512
--- strace-5.1.orig/tests-m32/ioctl_evdev-success.c	2020-01-27 19:35:30.932507172 +0100
86f512
+++ strace-5.1/tests-m32/ioctl_evdev-success.c	2020-01-29 12:39:23.992766667 +0100
86f512
@@ -56,6 +56,9 @@
86f512
 print_input_absinfo(long rc, const void *ptr, const void *arg)
86f512
 {
86f512
 	const struct input_absinfo *absinfo = ptr;
86f512
+# if VERBOSE
86f512
+	const uintptr_t sz = (uintptr_t) arg;
86f512
+# endif
86f512
 
86f512
 	if (rc < 0) {
86f512
 		printf("%p", absinfo);
86f512
@@ -67,9 +70,20 @@
86f512
 	PRINT_FIELD_U(", ", *absinfo, maximum);
86f512
 	PRINT_FIELD_U(", ", *absinfo, fuzz);
86f512
 	PRINT_FIELD_U(", ", *absinfo, flat);
86f512
+	if (sz > offsetofend(struct input_absinfo, flat)) {
86f512
+		if (sz >= 24) {
86f512
 #  ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
86f512
-	PRINT_FIELD_U(", ", *absinfo, resolution);
86f512
+			PRINT_FIELD_U(", ", *absinfo, resolution);
86f512
+#  else
86f512
+			printf(", resolution=%u", *((int *) ptr + 5));
86f512
 #  endif
86f512
+
86f512
+			if (sz > 24)
86f512
+				printf(", ...");
86f512
+		} else {
86f512
+			printf(", ...");
86f512
+		}
86f512
+	}
86f512
 # else
86f512
 	printf(", ...");
86f512
 # endif
86f512
@@ -176,10 +190,22 @@
86f512
 				   ", EVIOCGID, NULL) returning %lu",
86f512
 				   inject_retval);
86f512
 
86f512
+	static const void *absinfo_sz =
86f512
+		(const void *) (uintptr_t) sizeof(struct input_absinfo);
86f512
+
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_id, id);
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_absinfo, absinfo);
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(int, bad_addr_slot);
86f512
 
86f512
+	struct input_absinfo *absinfo_24 = tail_alloc(MAX(sizeof(*absinfo_24),
86f512
+							  24));
86f512
+	struct input_absinfo *absinfo_32 = tail_alloc(MAX(sizeof(*absinfo_32),
86f512
+							  32));
86f512
+
86f512
+	fill_memory(absinfo, sizeof(struct input_absinfo));
86f512
+	fill_memory(absinfo_24, 24);
86f512
+	fill_memory(absinfo_32, 32);
86f512
+
86f512
 # ifdef EVIOCGMTSLOTS
86f512
 	int mtslots[] = { ABS_MT_SLOT, 1, 3 };
86f512
 	/* we use the second element to indicate the number of values */
86f512
@@ -236,9 +262,26 @@
86f512
 		const void *ptr;
86f512
 	} a[] = {
86f512
 		{ { ARG_STR(EVIOCGID), id, print_input_id }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 19), "EVIOCGABS(ABS_Y)",
86f512
+		    absinfo, NULL }, NULL },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 20),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 20 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 21),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_24, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 21 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 24),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_24, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 24 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 32),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_32, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 32 },
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz},
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz },
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz },
86f512
 		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_more, print_getbit },
86f512
 			inject_retval * 8 <= EV_LED
86f512
 				? (const void *) &ev_more_str_2
86f512
Index: strace-5.1/tests-mx32/ioctl_evdev-success.c
86f512
===================================================================
86f512
--- strace-5.1.orig/tests-mx32/ioctl_evdev-success.c	2020-01-27 19:35:30.933507163 +0100
86f512
+++ strace-5.1/tests-mx32/ioctl_evdev-success.c	2020-01-29 12:39:23.994766648 +0100
86f512
@@ -56,6 +56,9 @@
86f512
 print_input_absinfo(long rc, const void *ptr, const void *arg)
86f512
 {
86f512
 	const struct input_absinfo *absinfo = ptr;
86f512
+# if VERBOSE
86f512
+	const uintptr_t sz = (uintptr_t) arg;
86f512
+# endif
86f512
 
86f512
 	if (rc < 0) {
86f512
 		printf("%p", absinfo);
86f512
@@ -67,9 +70,20 @@
86f512
 	PRINT_FIELD_U(", ", *absinfo, maximum);
86f512
 	PRINT_FIELD_U(", ", *absinfo, fuzz);
86f512
 	PRINT_FIELD_U(", ", *absinfo, flat);
86f512
+	if (sz > offsetofend(struct input_absinfo, flat)) {
86f512
+		if (sz >= 24) {
86f512
 #  ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
86f512
-	PRINT_FIELD_U(", ", *absinfo, resolution);
86f512
+			PRINT_FIELD_U(", ", *absinfo, resolution);
86f512
+#  else
86f512
+			printf(", resolution=%u", *((int *) ptr + 5));
86f512
 #  endif
86f512
+
86f512
+			if (sz > 24)
86f512
+				printf(", ...");
86f512
+		} else {
86f512
+			printf(", ...");
86f512
+		}
86f512
+	}
86f512
 # else
86f512
 	printf(", ...");
86f512
 # endif
86f512
@@ -176,10 +190,22 @@
86f512
 				   ", EVIOCGID, NULL) returning %lu",
86f512
 				   inject_retval);
86f512
 
86f512
+	static const void *absinfo_sz =
86f512
+		(const void *) (uintptr_t) sizeof(struct input_absinfo);
86f512
+
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_id, id);
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_absinfo, absinfo);
86f512
 	TAIL_ALLOC_OBJECT_CONST_PTR(int, bad_addr_slot);
86f512
 
86f512
+	struct input_absinfo *absinfo_24 = tail_alloc(MAX(sizeof(*absinfo_24),
86f512
+							  24));
86f512
+	struct input_absinfo *absinfo_32 = tail_alloc(MAX(sizeof(*absinfo_32),
86f512
+							  32));
86f512
+
86f512
+	fill_memory(absinfo, sizeof(struct input_absinfo));
86f512
+	fill_memory(absinfo_24, 24);
86f512
+	fill_memory(absinfo_32, 32);
86f512
+
86f512
 # ifdef EVIOCGMTSLOTS
86f512
 	int mtslots[] = { ABS_MT_SLOT, 1, 3 };
86f512
 	/* we use the second element to indicate the number of values */
86f512
@@ -236,9 +262,26 @@
86f512
 		const void *ptr;
86f512
 	} a[] = {
86f512
 		{ { ARG_STR(EVIOCGID), id, print_input_id }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL },
86f512
-		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 19), "EVIOCGABS(ABS_Y)",
86f512
+		    absinfo, NULL }, NULL },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 20),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 20 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 21),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_24, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 21 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 24),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_24, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 24 },
86f512
+		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 32),
86f512
+		    "EVIOCGABS(ABS_Y)", absinfo_32, print_input_absinfo },
86f512
+		  (const void *) (uintptr_t) 32 },
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz},
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz },
86f512
+		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo },
86f512
+		  absinfo_sz },
86f512
 		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_more, print_getbit },
86f512
 			inject_retval * 8 <= EV_LED
86f512
 				? (const void *) &ev_more_str_2