From e286b9cbc0bd542bb441c5acb65fef5f58b71aef Mon Sep 17 00:00:00 2001 From: Zhibin Li <08826794brmt@gmail.com> Date: Wed, 1 Aug 2018 17:54:35 +0800 Subject: [PATCH] tests: check decoding of successful evdev ioctl * tests/ioctl_evdev-success.c: New file. * tests/ioctl_evdev-success-v.c: Likewise. * tests/ioctl_evdev-success.test: New test. * tests/ioctl_evdev-success-v.test: Likewise. * tests/.gitignore: Add ioctl_evdev-success and ioctl_evdev-success-v. * tests/Makefile.am (check_PROGRAMS): Likewise. (DECODER_TESTS): Add the two tests mentioned above. Skipped files (not present in the tarball): tests/.gitignore Additional changes: tests/Makefile.in (generated from tests/Makefile.am) tests-m32/Makefile.am (generated from tests/Makefile.am) tests-m32/Makefile.in (generated from tests-m32/Makefile.am) tests-m32/ioctl_evdev-success-v.c (copy of tests/ioctl_evdev-success-v.c) tests-m32/ioctl_evdev-success-v.test (copy of tests/ioctl_evdev-success-v.test) tests-m32/ioctl_evdev-success.c (copy of tests/ioctl_evdev-success.c) tests-m32/ioctl_evdev-success.test (copy of tests/ioctl_evdev-success.test) tests-mx32/Makefile.am (generated from tests/Makefile.am) tests-mx32/Makefile.in (generated from tests-mx32/Makefile.am) tests-mx32/ioctl_evdev-success-v.c (copy of tests/ioctl_evdev-success-v.c) tests-mx32/ioctl_evdev-success-v.test (copy of tests/ioctl_evdev-success-v.test) tests-mx32/ioctl_evdev-success.c (copy of tests/ioctl_evdev-success.c) tests-mx32/ioctl_evdev-success.test (copy of tests/ioctl_evdev-success.test) --- tests/.gitignore | 2 + tests/Makefile.am | 4 + tests/ioctl_evdev-success-v.c | 2 + tests/ioctl_evdev-success-v.test | 13 +++ tests/ioctl_evdev-success.c | 232 +++++++++++++++++++++++++++++++++++++++ tests/ioctl_evdev-success.test | 13 +++ 6 files changed, 266 insertions(+) create mode 100644 tests/ioctl_evdev-success-v.c create mode 100755 tests/ioctl_evdev-success-v.test create mode 100644 tests/ioctl_evdev-success.c create mode 100755 tests/ioctl_evdev-success.test Index: strace-4.24/tests/Makefile.am =================================================================== --- strace-4.24.orig/tests/Makefile.am 2019-08-01 18:40:47.334658983 +0200 +++ strace-4.24/tests/Makefile.am 2019-08-01 18:40:47.365658583 +0200 @@ -98,6 +98,8 @@ int_0x80 \ ioctl_dm-v \ ioctl_evdev-v \ + ioctl_evdev-success \ + ioctl_evdev-success-v \ ioctl_loop-nv \ ioctl_loop-v \ ioctl_nsfs \ @@ -231,6 +233,8 @@ futex.test \ getuid.test \ ioctl.test \ + ioctl_evdev-success.test \ + ioctl_evdev-success-v.test \ ioctl_perf-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ Index: strace-4.24/tests-m32/Makefile.am =================================================================== --- strace-4.24.orig/tests-m32/Makefile.am 2018-08-14 02:44:30.000000000 +0200 +++ strace-4.24/tests-m32/Makefile.am 2019-08-01 18:40:47.365658583 +0200 @@ -118,6 +118,8 @@ int_0x80 \ ioctl_dm-v \ ioctl_evdev-v \ + ioctl_evdev-success \ + ioctl_evdev-success-v \ ioctl_loop-nv \ ioctl_loop-v \ ioctl_nsfs \ @@ -247,6 +249,8 @@ futex.test \ getuid.test \ ioctl.test \ + ioctl_evdev-success.test \ + ioctl_evdev-success-v.test \ ioctl_perf-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ Index: strace-4.24/tests-mx32/Makefile.am =================================================================== --- strace-4.24.orig/tests-mx32/Makefile.am 2018-08-14 02:44:30.000000000 +0200 +++ strace-4.24/tests-mx32/Makefile.am 2019-08-01 18:40:47.366658571 +0200 @@ -118,6 +118,8 @@ int_0x80 \ ioctl_dm-v \ ioctl_evdev-v \ + ioctl_evdev-success \ + ioctl_evdev-success-v \ ioctl_loop-nv \ ioctl_loop-v \ ioctl_nsfs \ @@ -247,6 +249,8 @@ futex.test \ getuid.test \ ioctl.test \ + ioctl_evdev-success.test \ + ioctl_evdev-success-v.test \ ioctl_perf-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ Index: strace-4.24/tests/ioctl_evdev-success-v.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests/ioctl_evdev-success-v.c 2019-08-01 18:40:47.366658571 +0200 @@ -0,0 +1,2 @@ +#define VERBOSE 1 +#include "ioctl_evdev-success.c" Index: strace-4.24/tests-m32/ioctl_evdev-success-v.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests-m32/ioctl_evdev-success-v.c 2019-08-01 18:40:47.366658571 +0200 @@ -0,0 +1,2 @@ +#define VERBOSE 1 +#include "ioctl_evdev-success.c" Index: strace-4.24/tests-mx32/ioctl_evdev-success-v.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests-mx32/ioctl_evdev-success-v.c 2019-08-01 18:40:47.366658571 +0200 @@ -0,0 +1,2 @@ +#define VERBOSE 1 +#include "ioctl_evdev-success.c" Index: strace-4.24/tests/ioctl_evdev-success-v.test =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests/ioctl_evdev-success-v.test 2019-08-01 18:40:58.009521546 +0200 @@ -0,0 +1,13 @@ +#!/bin/sh -efu + +. "${srcdir=.}/scno_tampering.sh" + +: ${IOCTL_INJECT_START=256} +: ${IOCTL_INJECT_RETVAL=8} + +run_prog +run_strace -a16 -v -e trace=ioctl \ + -e inject=ioctl:retval="${IOCTL_INJECT_RETVAL}":when="${IOCTL_INJECT_START}+" \ + ../ioctl_evdev-success-v "${IOCTL_INJECT_START}" "${IOCTL_INJECT_RETVAL}"> "$EXP" +grep -v '^ioctl([012][,<]' < "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" Index: strace-4.24/tests-m32/ioctl_evdev-success-v.test =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests-m32/ioctl_evdev-success-v.test 2019-08-01 18:40:58.009521546 +0200 @@ -0,0 +1,13 @@ +#!/bin/sh -efu + +. "${srcdir=.}/scno_tampering.sh" + +: ${IOCTL_INJECT_START=256} +: ${IOCTL_INJECT_RETVAL=8} + +run_prog +run_strace -a16 -v -e trace=ioctl \ + -e inject=ioctl:retval="${IOCTL_INJECT_RETVAL}":when="${IOCTL_INJECT_START}+" \ + ../ioctl_evdev-success-v "${IOCTL_INJECT_START}" "${IOCTL_INJECT_RETVAL}"> "$EXP" +grep -v '^ioctl([012][,<]' < "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" Index: strace-4.24/tests-mx32/ioctl_evdev-success-v.test =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests-mx32/ioctl_evdev-success-v.test 2019-08-01 18:40:58.009521546 +0200 @@ -0,0 +1,13 @@ +#!/bin/sh -efu + +. "${srcdir=.}/scno_tampering.sh" + +: ${IOCTL_INJECT_START=256} +: ${IOCTL_INJECT_RETVAL=8} + +run_prog +run_strace -a16 -v -e trace=ioctl \ + -e inject=ioctl:retval="${IOCTL_INJECT_RETVAL}":when="${IOCTL_INJECT_START}+" \ + ../ioctl_evdev-success-v "${IOCTL_INJECT_START}" "${IOCTL_INJECT_RETVAL}"> "$EXP" +grep -v '^ioctl([012][,<]' < "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" Index: strace-4.24/tests/ioctl_evdev-success.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests/ioctl_evdev-success.c 2019-08-01 18:40:58.009521546 +0200 @@ -0,0 +1,232 @@ +#include "tests.h" + +#ifdef HAVE_LINUX_INPUT_H + +# include +# include +# include +# include +# include +# include "print_fields.h" + +static const char *errstr; + +struct evdev_check { + unsigned long cmd; + const char *cmd_str; + void *arg_ptr; + void (*print_arg)(long rc, void *ptr, void *arg); +}; + +static long +invoke_test_syscall(unsigned long cmd, void *p) +{ + long rc = ioctl(-1, cmd, p); + errstr = sprintrc(rc); + static char inj_errstr[4096]; + + snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr); + errstr = inj_errstr; + return rc; +} + +static void +test_evdev(struct evdev_check *check, void *arg) +{ + long rc = invoke_test_syscall(check->cmd, check->arg_ptr); + printf("ioctl(-1, %s, ", check->cmd_str); + if (check->print_arg) + check->print_arg(rc, check->arg_ptr, arg); + else + printf("%p", check->arg_ptr); + printf(") = %s\n", errstr); +} + +static void +print_input_absinfo(long rc, void *ptr, void *arg) +{ + struct input_absinfo *absinfo = ptr; + + if (rc < 0) { + printf("%p", absinfo); + return; + } + PRINT_FIELD_U("{", *absinfo, value); + PRINT_FIELD_U(", ", *absinfo, minimum); +# if VERBOSE + PRINT_FIELD_U(", ", *absinfo, maximum); + PRINT_FIELD_U(", ", *absinfo, fuzz); + PRINT_FIELD_U(", ", *absinfo, flat); +# ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION + PRINT_FIELD_U(", ", *absinfo, resolution); +# endif +# else + printf(", ..."); +# endif + printf("}"); +} + +static void +print_input_id(long rc, void *ptr, void *arg) +{ + struct input_id *id = ptr; + + if (rc < 0) { + printf("%p", id); + return; + } + printf("{ID_BUS=%" PRIu16 + ", ID_VENDOR=%" PRIu16 + ", ID_PRODUCT=%" PRIu16 + ", ID_VERSION=%" PRIu16 "}", + id->bustype, id->vendor, id->product, id->version); +} + +# ifdef EVIOCGMTSLOTS +static void +print_mtslots(long rc, void *ptr, void *arg) +{ + int *buffer = ptr; + const char **str = arg; + int num = atoi(*(str + 1)); + + if (rc < 0) { + printf("%p", buffer); + return; + } + + printf("{code=%s", *str); + printf(", values=["); + for (unsigned int i = 1; i <= (unsigned) num; i++) + printf("%s%s", i > 1 ? ", " : "", *(str + i + 1)); + printf("]}"); +} +# endif + +static void +print_getbit(long rc, void *ptr, void *arg) +{ + const char **str = arg; + int num = atoi(*str); + + if (rc < 0) { + printf("%p", ptr); + return; + } + + printf("["); + printf("%s", *(str + 1)); + for (unsigned int i = 2; i <= (unsigned) num; i++) { +# if ! VERBOSE + if (i > 4) { + printf(", ..."); + break; + } +# endif + printf(", "); + printf("%s", *(str + i)); + } + printf("]"); +} + +int +main(int argc, char **argv) +{ + unsigned long num_skip; + long inject_retval; + bool locked = false; + + if (argc == 1) + return 0; + + if (argc < 3) + error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]); + + num_skip = strtoul(argv[1], NULL, 0); + inject_retval = strtol(argv[2], NULL, 0); + + if (inject_retval < 0) + error_msg_and_fail("Expected non-negative INJECT_RETVAL, " + "but got %ld", inject_retval); + + for (unsigned int i = 0; i < num_skip; i++) { + long rc = ioctl(-1, EVIOCGID, NULL); + printf("ioctl(-1, EVIOCGID, NULL) = %s%s\n", + sprintrc(rc), + rc == inject_retval ? " (INJECTED)" : ""); + + if (rc != inject_retval) + continue; + + locked = true; + break; + } + + if (!locked) + error_msg_and_fail("Hasn't locked on ioctl(-1" + ", EVIOCGID, NULL) returning %lu", + inject_retval); + + TAIL_ALLOC_OBJECT_CONST_PTR(struct input_id, id); + TAIL_ALLOC_OBJECT_CONST_PTR(struct input_absinfo, absinfo); + TAIL_ALLOC_OBJECT_CONST_PTR(int, bad_addr_slot); +# ifdef EVIOCGMTSLOTS + int mtslots[] = { ABS_MT_SLOT, 1, 3 }; + /* we use the second element to indicate the number of values */ + /* mtslots_str[1] is "2" so the number of values is 2 */ + const char *mtslots_str[] = { "ABS_MT_SLOT", "2", "1", "3" }; + + /* invalid flag */ + int invalid_mtslot[] = { -1, 1 }; + char invalid_str[4096]; + snprintf(invalid_str, sizeof(invalid_str), "%#x /* ABS_MT_??? */", invalid_mtslot[0]); + const char *invalid_mtslot_str[] = { invalid_str, "1", "1" }; +# endif + + /* set more than 4 bits */ + unsigned long ev_more[] = { 1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED | 1 << EV_SND | 1 << EV_PWR }; + /* we use the first element to indicate the number of set bits */ + /* ev_more_str[0] is "5" so the number of set bits is 5 */ + const char *ev_more_str[] = { "5", "EV_ABS", "EV_MSC", "EV_LED", "EV_SND", "EV_PWR" }; + + /* set less than 4 bits */ + unsigned long ev_less[] = { 1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED }; + const char *ev_less_str[] = { "3", "EV_ABS", "EV_MSC", "EV_LED" }; + + /* set zero bit */ + unsigned long ev_zero[] = { 0x0 }; + const char *ev_zero_str[] = { "0", " 0 " }; + + /* KEY_MAX is 0x2ff which is greater than retval * 8 */ + unsigned long key[] = { 1 << KEY_1 | 1 << KEY_2, 0 }; + const char *key_str[] = { "2", "KEY_1", "KEY_2" }; + + struct { + struct evdev_check check; + void *ptr; + } a[] = { + { { ARG_STR(EVIOCGID), id, print_input_id }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_more, print_getbit }, &ev_more_str }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_less, print_getbit }, &ev_less_str }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_zero, print_getbit }, &ev_zero_str }, + { { ARG_STR(EVIOCGBIT(EV_KEY, 0)), key, print_getbit }, &key_str}, +# ifdef EVIOCGMTSLOTS + { { ARG_STR(EVIOCGMTSLOTS(12)), mtslots, print_mtslots }, &mtslots_str }, + { { ARG_STR(EVIOCGMTSLOTS(8)), invalid_mtslot, print_mtslots }, &invalid_mtslot_str } +# endif + }; + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { + test_evdev(&a[i].check, a[i].ptr); + } + + puts("+++ exited with 0 +++"); + return 0; +} +#else + +SKIP_MAIN_UNDEFINED("HAVE_LINUX_INPUT_H") + +#endif Index: strace-4.24/tests-m32/ioctl_evdev-success.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests-m32/ioctl_evdev-success.c 2019-08-01 18:40:47.367658558 +0200 @@ -0,0 +1,232 @@ +#include "tests.h" + +#ifdef HAVE_LINUX_INPUT_H + +# include +# include +# include +# include +# include +# include "print_fields.h" + +static const char *errstr; + +struct evdev_check { + unsigned long cmd; + const char *cmd_str; + void *arg_ptr; + void (*print_arg)(long rc, void *ptr, void *arg); +}; + +static long +invoke_test_syscall(unsigned long cmd, void *p) +{ + long rc = ioctl(-1, cmd, p); + errstr = sprintrc(rc); + static char inj_errstr[4096]; + + snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr); + errstr = inj_errstr; + return rc; +} + +static void +test_evdev(struct evdev_check *check, void *arg) +{ + long rc = invoke_test_syscall(check->cmd, check->arg_ptr); + printf("ioctl(-1, %s, ", check->cmd_str); + if (check->print_arg) + check->print_arg(rc, check->arg_ptr, arg); + else + printf("%p", check->arg_ptr); + printf(") = %s\n", errstr); +} + +static void +print_input_absinfo(long rc, void *ptr, void *arg) +{ + struct input_absinfo *absinfo = ptr; + + if (rc < 0) { + printf("%p", absinfo); + return; + } + PRINT_FIELD_U("{", *absinfo, value); + PRINT_FIELD_U(", ", *absinfo, minimum); +# if VERBOSE + PRINT_FIELD_U(", ", *absinfo, maximum); + PRINT_FIELD_U(", ", *absinfo, fuzz); + PRINT_FIELD_U(", ", *absinfo, flat); +# ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION + PRINT_FIELD_U(", ", *absinfo, resolution); +# endif +# else + printf(", ..."); +# endif + printf("}"); +} + +static void +print_input_id(long rc, void *ptr, void *arg) +{ + struct input_id *id = ptr; + + if (rc < 0) { + printf("%p", id); + return; + } + printf("{ID_BUS=%" PRIu16 + ", ID_VENDOR=%" PRIu16 + ", ID_PRODUCT=%" PRIu16 + ", ID_VERSION=%" PRIu16 "}", + id->bustype, id->vendor, id->product, id->version); +} + +# ifdef EVIOCGMTSLOTS +static void +print_mtslots(long rc, void *ptr, void *arg) +{ + int *buffer = ptr; + const char **str = arg; + int num = atoi(*(str + 1)); + + if (rc < 0) { + printf("%p", buffer); + return; + } + + printf("{code=%s", *str); + printf(", values=["); + for (unsigned int i = 1; i <= (unsigned) num; i++) + printf("%s%s", i > 1 ? ", " : "", *(str + i + 1)); + printf("]}"); +} +# endif + +static void +print_getbit(long rc, void *ptr, void *arg) +{ + const char **str = arg; + int num = atoi(*str); + + if (rc < 0) { + printf("%p", ptr); + return; + } + + printf("["); + printf("%s", *(str + 1)); + for (unsigned int i = 2; i <= (unsigned) num; i++) { +# if ! VERBOSE + if (i > 4) { + printf(", ..."); + break; + } +# endif + printf(", "); + printf("%s", *(str + i)); + } + printf("]"); +} + +int +main(int argc, char **argv) +{ + unsigned long num_skip; + long inject_retval; + bool locked = false; + + if (argc == 1) + return 0; + + if (argc < 3) + error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]); + + num_skip = strtoul(argv[1], NULL, 0); + inject_retval = strtol(argv[2], NULL, 0); + + if (inject_retval < 0) + error_msg_and_fail("Expected non-negative INJECT_RETVAL, " + "but got %ld", inject_retval); + + for (unsigned int i = 0; i < num_skip; i++) { + long rc = ioctl(-1, EVIOCGID, NULL); + printf("ioctl(-1, EVIOCGID, NULL) = %s%s\n", + sprintrc(rc), + rc == inject_retval ? " (INJECTED)" : ""); + + if (rc != inject_retval) + continue; + + locked = true; + break; + } + + if (!locked) + error_msg_and_fail("Hasn't locked on ioctl(-1" + ", EVIOCGID, NULL) returning %lu", + inject_retval); + + TAIL_ALLOC_OBJECT_CONST_PTR(struct input_id, id); + TAIL_ALLOC_OBJECT_CONST_PTR(struct input_absinfo, absinfo); + TAIL_ALLOC_OBJECT_CONST_PTR(int, bad_addr_slot); +# ifdef EVIOCGMTSLOTS + int mtslots[] = { ABS_MT_SLOT, 1, 3 }; + /* we use the second element to indicate the number of values */ + /* mtslots_str[1] is "2" so the number of values is 2 */ + const char *mtslots_str[] = { "ABS_MT_SLOT", "2", "1", "3" }; + + /* invalid flag */ + int invalid_mtslot[] = { -1, 1 }; + char invalid_str[4096]; + snprintf(invalid_str, sizeof(invalid_str), "%#x /* ABS_MT_??? */", invalid_mtslot[0]); + const char *invalid_mtslot_str[] = { invalid_str, "1", "1" }; +# endif + + /* set more than 4 bits */ + unsigned long ev_more[] = { 1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED | 1 << EV_SND | 1 << EV_PWR }; + /* we use the first element to indicate the number of set bits */ + /* ev_more_str[0] is "5" so the number of set bits is 5 */ + const char *ev_more_str[] = { "5", "EV_ABS", "EV_MSC", "EV_LED", "EV_SND", "EV_PWR" }; + + /* set less than 4 bits */ + unsigned long ev_less[] = { 1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED }; + const char *ev_less_str[] = { "3", "EV_ABS", "EV_MSC", "EV_LED" }; + + /* set zero bit */ + unsigned long ev_zero[] = { 0x0 }; + const char *ev_zero_str[] = { "0", " 0 " }; + + /* KEY_MAX is 0x2ff which is greater than retval * 8 */ + unsigned long key[] = { 1 << KEY_1 | 1 << KEY_2, 0 }; + const char *key_str[] = { "2", "KEY_1", "KEY_2" }; + + struct { + struct evdev_check check; + void *ptr; + } a[] = { + { { ARG_STR(EVIOCGID), id, print_input_id }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_more, print_getbit }, &ev_more_str }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_less, print_getbit }, &ev_less_str }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_zero, print_getbit }, &ev_zero_str }, + { { ARG_STR(EVIOCGBIT(EV_KEY, 0)), key, print_getbit }, &key_str}, +# ifdef EVIOCGMTSLOTS + { { ARG_STR(EVIOCGMTSLOTS(12)), mtslots, print_mtslots }, &mtslots_str }, + { { ARG_STR(EVIOCGMTSLOTS(8)), invalid_mtslot, print_mtslots }, &invalid_mtslot_str } +# endif + }; + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { + test_evdev(&a[i].check, a[i].ptr); + } + + puts("+++ exited with 0 +++"); + return 0; +} +#else + +SKIP_MAIN_UNDEFINED("HAVE_LINUX_INPUT_H") + +#endif Index: strace-4.24/tests-mx32/ioctl_evdev-success.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests-mx32/ioctl_evdev-success.c 2019-08-01 18:40:47.367658558 +0200 @@ -0,0 +1,232 @@ +#include "tests.h" + +#ifdef HAVE_LINUX_INPUT_H + +# include +# include +# include +# include +# include +# include "print_fields.h" + +static const char *errstr; + +struct evdev_check { + unsigned long cmd; + const char *cmd_str; + void *arg_ptr; + void (*print_arg)(long rc, void *ptr, void *arg); +}; + +static long +invoke_test_syscall(unsigned long cmd, void *p) +{ + long rc = ioctl(-1, cmd, p); + errstr = sprintrc(rc); + static char inj_errstr[4096]; + + snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr); + errstr = inj_errstr; + return rc; +} + +static void +test_evdev(struct evdev_check *check, void *arg) +{ + long rc = invoke_test_syscall(check->cmd, check->arg_ptr); + printf("ioctl(-1, %s, ", check->cmd_str); + if (check->print_arg) + check->print_arg(rc, check->arg_ptr, arg); + else + printf("%p", check->arg_ptr); + printf(") = %s\n", errstr); +} + +static void +print_input_absinfo(long rc, void *ptr, void *arg) +{ + struct input_absinfo *absinfo = ptr; + + if (rc < 0) { + printf("%p", absinfo); + return; + } + PRINT_FIELD_U("{", *absinfo, value); + PRINT_FIELD_U(", ", *absinfo, minimum); +# if VERBOSE + PRINT_FIELD_U(", ", *absinfo, maximum); + PRINT_FIELD_U(", ", *absinfo, fuzz); + PRINT_FIELD_U(", ", *absinfo, flat); +# ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION + PRINT_FIELD_U(", ", *absinfo, resolution); +# endif +# else + printf(", ..."); +# endif + printf("}"); +} + +static void +print_input_id(long rc, void *ptr, void *arg) +{ + struct input_id *id = ptr; + + if (rc < 0) { + printf("%p", id); + return; + } + printf("{ID_BUS=%" PRIu16 + ", ID_VENDOR=%" PRIu16 + ", ID_PRODUCT=%" PRIu16 + ", ID_VERSION=%" PRIu16 "}", + id->bustype, id->vendor, id->product, id->version); +} + +# ifdef EVIOCGMTSLOTS +static void +print_mtslots(long rc, void *ptr, void *arg) +{ + int *buffer = ptr; + const char **str = arg; + int num = atoi(*(str + 1)); + + if (rc < 0) { + printf("%p", buffer); + return; + } + + printf("{code=%s", *str); + printf(", values=["); + for (unsigned int i = 1; i <= (unsigned) num; i++) + printf("%s%s", i > 1 ? ", " : "", *(str + i + 1)); + printf("]}"); +} +# endif + +static void +print_getbit(long rc, void *ptr, void *arg) +{ + const char **str = arg; + int num = atoi(*str); + + if (rc < 0) { + printf("%p", ptr); + return; + } + + printf("["); + printf("%s", *(str + 1)); + for (unsigned int i = 2; i <= (unsigned) num; i++) { +# if ! VERBOSE + if (i > 4) { + printf(", ..."); + break; + } +# endif + printf(", "); + printf("%s", *(str + i)); + } + printf("]"); +} + +int +main(int argc, char **argv) +{ + unsigned long num_skip; + long inject_retval; + bool locked = false; + + if (argc == 1) + return 0; + + if (argc < 3) + error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]); + + num_skip = strtoul(argv[1], NULL, 0); + inject_retval = strtol(argv[2], NULL, 0); + + if (inject_retval < 0) + error_msg_and_fail("Expected non-negative INJECT_RETVAL, " + "but got %ld", inject_retval); + + for (unsigned int i = 0; i < num_skip; i++) { + long rc = ioctl(-1, EVIOCGID, NULL); + printf("ioctl(-1, EVIOCGID, NULL) = %s%s\n", + sprintrc(rc), + rc == inject_retval ? " (INJECTED)" : ""); + + if (rc != inject_retval) + continue; + + locked = true; + break; + } + + if (!locked) + error_msg_and_fail("Hasn't locked on ioctl(-1" + ", EVIOCGID, NULL) returning %lu", + inject_retval); + + TAIL_ALLOC_OBJECT_CONST_PTR(struct input_id, id); + TAIL_ALLOC_OBJECT_CONST_PTR(struct input_absinfo, absinfo); + TAIL_ALLOC_OBJECT_CONST_PTR(int, bad_addr_slot); +# ifdef EVIOCGMTSLOTS + int mtslots[] = { ABS_MT_SLOT, 1, 3 }; + /* we use the second element to indicate the number of values */ + /* mtslots_str[1] is "2" so the number of values is 2 */ + const char *mtslots_str[] = { "ABS_MT_SLOT", "2", "1", "3" }; + + /* invalid flag */ + int invalid_mtslot[] = { -1, 1 }; + char invalid_str[4096]; + snprintf(invalid_str, sizeof(invalid_str), "%#x /* ABS_MT_??? */", invalid_mtslot[0]); + const char *invalid_mtslot_str[] = { invalid_str, "1", "1" }; +# endif + + /* set more than 4 bits */ + unsigned long ev_more[] = { 1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED | 1 << EV_SND | 1 << EV_PWR }; + /* we use the first element to indicate the number of set bits */ + /* ev_more_str[0] is "5" so the number of set bits is 5 */ + const char *ev_more_str[] = { "5", "EV_ABS", "EV_MSC", "EV_LED", "EV_SND", "EV_PWR" }; + + /* set less than 4 bits */ + unsigned long ev_less[] = { 1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED }; + const char *ev_less_str[] = { "3", "EV_ABS", "EV_MSC", "EV_LED" }; + + /* set zero bit */ + unsigned long ev_zero[] = { 0x0 }; + const char *ev_zero_str[] = { "0", " 0 " }; + + /* KEY_MAX is 0x2ff which is greater than retval * 8 */ + unsigned long key[] = { 1 << KEY_1 | 1 << KEY_2, 0 }; + const char *key_str[] = { "2", "KEY_1", "KEY_2" }; + + struct { + struct evdev_check check; + void *ptr; + } a[] = { + { { ARG_STR(EVIOCGID), id, print_input_id }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_more, print_getbit }, &ev_more_str }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_less, print_getbit }, &ev_less_str }, + { { ARG_STR(EVIOCGBIT(0, 0)), ev_zero, print_getbit }, &ev_zero_str }, + { { ARG_STR(EVIOCGBIT(EV_KEY, 0)), key, print_getbit }, &key_str}, +# ifdef EVIOCGMTSLOTS + { { ARG_STR(EVIOCGMTSLOTS(12)), mtslots, print_mtslots }, &mtslots_str }, + { { ARG_STR(EVIOCGMTSLOTS(8)), invalid_mtslot, print_mtslots }, &invalid_mtslot_str } +# endif + }; + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { + test_evdev(&a[i].check, a[i].ptr); + } + + puts("+++ exited with 0 +++"); + return 0; +} +#else + +SKIP_MAIN_UNDEFINED("HAVE_LINUX_INPUT_H") + +#endif Index: strace-4.24/tests/ioctl_evdev-success.test =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests/ioctl_evdev-success.test 2019-08-01 18:40:58.009521546 +0200 @@ -0,0 +1,13 @@ +#!/bin/sh -efu + +. "${srcdir=.}/scno_tampering.sh" + +: ${IOCTL_INJECT_START=256} +: ${IOCTL_INJECT_RETVAL=8} + +run_prog +run_strace -a16 -e trace=ioctl \ + -e inject=ioctl:retval="${IOCTL_INJECT_RETVAL}":when="${IOCTL_INJECT_START}+" \ + ../ioctl_evdev-success "${IOCTL_INJECT_START}" "${IOCTL_INJECT_RETVAL}"> "$EXP" +grep -v '^ioctl([012][,<]' < "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" Index: strace-4.24/tests-m32/ioctl_evdev-success.test =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests-m32/ioctl_evdev-success.test 2019-08-01 18:40:58.009521546 +0200 @@ -0,0 +1,13 @@ +#!/bin/sh -efu + +. "${srcdir=.}/scno_tampering.sh" + +: ${IOCTL_INJECT_START=256} +: ${IOCTL_INJECT_RETVAL=8} + +run_prog +run_strace -a16 -e trace=ioctl \ + -e inject=ioctl:retval="${IOCTL_INJECT_RETVAL}":when="${IOCTL_INJECT_START}+" \ + ../ioctl_evdev-success "${IOCTL_INJECT_START}" "${IOCTL_INJECT_RETVAL}"> "$EXP" +grep -v '^ioctl([012][,<]' < "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" Index: strace-4.24/tests-mx32/ioctl_evdev-success.test =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ strace-4.24/tests-mx32/ioctl_evdev-success.test 2019-08-01 18:40:58.009521546 +0200 @@ -0,0 +1,13 @@ +#!/bin/sh -efu + +. "${srcdir=.}/scno_tampering.sh" + +: ${IOCTL_INJECT_START=256} +: ${IOCTL_INJECT_RETVAL=8} + +run_prog +run_strace -a16 -e trace=ioctl \ + -e inject=ioctl:retval="${IOCTL_INJECT_RETVAL}":when="${IOCTL_INJECT_START}+" \ + ../ioctl_evdev-success "${IOCTL_INJECT_START}" "${IOCTL_INJECT_RETVAL}"> "$EXP" +grep -v '^ioctl([012][,<]' < "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" Index: strace-4.24/tests/Makefile.in =================================================================== --- strace-4.24.orig/tests/Makefile.in 2019-08-01 18:40:47.308659317 +0200 +++ strace-4.24/tests/Makefile.in 2019-08-01 19:16:24.800947844 +0200 @@ -150,7 +150,8 @@ filter-unavailable$(EXEEXT) fork-f$(EXEEXT) fsync-y$(EXEEXT) \ getpid$(EXEEXT) getppid$(EXEEXT) gettid$(EXEEXT) \ inject-nf$(EXEEXT) int_0x80$(EXEEXT) ioctl_dm-v$(EXEEXT) \ - ioctl_evdev-v$(EXEEXT) ioctl_loop-nv$(EXEEXT) \ + ioctl_evdev-v$(EXEEXT) ioctl_evdev-success$(EXEEXT) \ + ioctl_evdev-success-v$(EXEEXT) ioctl_loop-nv$(EXEEXT) \ ioctl_loop-v$(EXEEXT) ioctl_nsfs$(EXEEXT) \ ioctl_perf-success$(EXEEXT) ioctl_rtc-v$(EXEEXT) \ is_linux_mips_n64$(EXEEXT) kill_child$(EXEEXT) \ @@ -974,6 +975,14 @@ ioctl_evdev_OBJECTS = ioctl_evdev.$(OBJEXT) ioctl_evdev_LDADD = $(LDADD) ioctl_evdev_DEPENDENCIES = libtests.a +ioctl_evdev_success_SOURCES = ioctl_evdev-success.c +ioctl_evdev_success_OBJECTS = ioctl_evdev-success.$(OBJEXT) +ioctl_evdev_success_LDADD = $(LDADD) +ioctl_evdev_success_DEPENDENCIES = libtests.a +ioctl_evdev_success_v_SOURCES = ioctl_evdev-success-v.c +ioctl_evdev_success_v_OBJECTS = ioctl_evdev-success-v.$(OBJEXT) +ioctl_evdev_success_v_LDADD = $(LDADD) +ioctl_evdev_success_v_DEPENDENCIES = libtests.a ioctl_evdev_v_SOURCES = ioctl_evdev-v.c ioctl_evdev_v_OBJECTS = ioctl_evdev-v.$(OBJEXT) ioctl_evdev_v_LDADD = $(LDADD) @@ -2740,11 +2749,12 @@ getuid.c getuid32.c getxxid.c group_req.c inet-cmsg.c \ init_module.c inject-nf.c inotify.c inotify_init1.c int_0x80.c \ ioctl.c ioctl_block.c ioctl_dm.c ioctl_dm-v.c ioctl_evdev.c \ - ioctl_evdev-v.c ioctl_inotify.c ioctl_kvm_run.c \ - ioctl_kvm_run-v.c ioctl_kvm_run_auxstr_vcpu.c ioctl_loop.c \ - ioctl_loop-nv.c ioctl_loop-v.c ioctl_mtd.c ioctl_nsfs.c \ - ioctl_perf.c ioctl_perf-success.c ioctl_ptp.c ioctl_rtc.c \ - ioctl_rtc-v.c ioctl_scsi.c ioctl_sg_io_v3.c ioctl_sg_io_v4.c \ + ioctl_evdev-success.c ioctl_evdev-success-v.c ioctl_evdev-v.c \ + ioctl_inotify.c ioctl_kvm_run.c ioctl_kvm_run-v.c \ + ioctl_kvm_run_auxstr_vcpu.c ioctl_loop.c ioctl_loop-nv.c \ + ioctl_loop-v.c ioctl_mtd.c ioctl_nsfs.c ioctl_perf.c \ + ioctl_perf-success.c ioctl_ptp.c ioctl_rtc.c ioctl_rtc-v.c \ + ioctl_scsi.c ioctl_sg_io_v3.c ioctl_sg_io_v4.c \ ioctl_sock_gifconf.c ioctl_uffdio.c ioctl_v4l2.c ioperm.c \ iopl.c ioprio.c ip_mreq.c ipc.c ipc_msg.c ipc_msg-Xabbrev.c \ ipc_msg-Xraw.c ipc_msg-Xverbose.c ipc_msgbuf.c \ @@ -2887,11 +2897,12 @@ getuid.c getuid32.c getxxid.c group_req.c inet-cmsg.c \ init_module.c inject-nf.c inotify.c inotify_init1.c int_0x80.c \ ioctl.c ioctl_block.c ioctl_dm.c ioctl_dm-v.c ioctl_evdev.c \ - ioctl_evdev-v.c ioctl_inotify.c ioctl_kvm_run.c \ - ioctl_kvm_run-v.c ioctl_kvm_run_auxstr_vcpu.c ioctl_loop.c \ - ioctl_loop-nv.c ioctl_loop-v.c ioctl_mtd.c ioctl_nsfs.c \ - ioctl_perf.c ioctl_perf-success.c ioctl_ptp.c ioctl_rtc.c \ - ioctl_rtc-v.c ioctl_scsi.c ioctl_sg_io_v3.c ioctl_sg_io_v4.c \ + ioctl_evdev-success.c ioctl_evdev-success-v.c ioctl_evdev-v.c \ + ioctl_inotify.c ioctl_kvm_run.c ioctl_kvm_run-v.c \ + ioctl_kvm_run_auxstr_vcpu.c ioctl_loop.c ioctl_loop-nv.c \ + ioctl_loop-v.c ioctl_mtd.c ioctl_nsfs.c ioctl_perf.c \ + ioctl_perf-success.c ioctl_ptp.c ioctl_rtc.c ioctl_rtc-v.c \ + ioctl_scsi.c ioctl_sg_io_v3.c ioctl_sg_io_v4.c \ ioctl_sock_gifconf.c ioctl_uffdio.c ioctl_v4l2.c ioperm.c \ iopl.c ioprio.c ip_mreq.c ipc.c ipc_msg.c ipc_msg-Xabbrev.c \ ipc_msg-Xraw.c ipc_msg-Xverbose.c ipc_msgbuf.c \ @@ -4173,6 +4184,8 @@ futex.test \ getuid.test \ ioctl.test \ + ioctl_evdev-success.test \ + ioctl_evdev-success-v.test \ ioctl_perf-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ @@ -4998,6 +5011,14 @@ @rm -f ioctl_evdev$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ioctl_evdev_OBJECTS) $(ioctl_evdev_LDADD) $(LIBS) +ioctl_evdev-success$(EXEEXT): $(ioctl_evdev_success_OBJECTS) $(ioctl_evdev_success_DEPENDENCIES) $(EXTRA_ioctl_evdev_success_DEPENDENCIES) + @rm -f ioctl_evdev-success$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ioctl_evdev_success_OBJECTS) $(ioctl_evdev_success_LDADD) $(LIBS) + +ioctl_evdev-success-v$(EXEEXT): $(ioctl_evdev_success_v_OBJECTS) $(ioctl_evdev_success_v_DEPENDENCIES) $(EXTRA_ioctl_evdev_success_v_DEPENDENCIES) + @rm -f ioctl_evdev-success-v$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ioctl_evdev_success_v_OBJECTS) $(ioctl_evdev_success_v_LDADD) $(LIBS) + ioctl_evdev-v$(EXEEXT): $(ioctl_evdev_v_OBJECTS) $(ioctl_evdev_v_DEPENDENCIES) $(EXTRA_ioctl_evdev_v_DEPENDENCIES) @rm -f ioctl_evdev-v$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ioctl_evdev_v_OBJECTS) $(ioctl_evdev_v_LDADD) $(LIBS) @@ -6833,6 +6854,8 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioctl_block.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioctl_dm-v.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioctl_dm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioctl_evdev-success-v.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioctl_evdev-success.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioctl_evdev-v.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioctl_evdev.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioctl_inotify.Po@am__quote@