(root)/
strace-6.5/
tests-m32/
ioctl_evdev-success.c
       1  /*
       2   * Copyright (c) 2018-2021 The strace developers.
       3   * All rights reserved.
       4   *
       5   * SPDX-License-Identifier: GPL-2.0-or-later
       6   */
       7  
       8  #include "tests.h"
       9  
      10  #include <assert.h>
      11  #include <inttypes.h>
      12  #include <stdio.h>
      13  #include <stdlib.h>
      14  #include <sys/ioctl.h>
      15  #include <linux/ioctl.h>
      16  #include <linux/input.h>
      17  #include "print_fields.h"
      18  
      19  #define NUM_WORDS 4
      20  
      21  static const char *errstr;
      22  
      23  struct evdev_check {
      24  	unsigned long cmd;
      25  	const char *cmd_str;
      26  	const void *arg_ptr;
      27  	void (*print_arg)(long rc, const void *ptr, const void *arg);
      28  };
      29  
      30  static long
      31  invoke_test_syscall(unsigned long cmd, const void *p)
      32  {
      33  	long rc = ioctl(-1, cmd, p);
      34  	errstr = sprintrc(rc);
      35  	static char inj_errstr[4096];
      36  
      37  	snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
      38  	errstr = inj_errstr;
      39  	return rc;
      40  }
      41  
      42  static void
      43  test_evdev(struct evdev_check *check, const void *arg)
      44  {
      45  	long rc = invoke_test_syscall(check->cmd, check->arg_ptr);
      46  	printf("ioctl(-1, %s, ", sprintxlat(check->cmd_str, check->cmd, NULL));
      47  	if (check->print_arg)
      48  		check->print_arg(rc, check->arg_ptr, arg);
      49  	else
      50  		printf("%p", check->arg_ptr);
      51  	printf(") = %s\n", errstr);
      52  }
      53  
      54  static void
      55  print_input_absinfo(long rc, const void *ptr, const void *arg)
      56  {
      57  	const struct input_absinfo *absinfo = ptr;
      58  #if VERBOSE
      59  	const uintptr_t sz = (uintptr_t) arg;
      60  #endif
      61  
      62  	if (rc < 0) {
      63  		printf("%p", absinfo);
      64  		return;
      65  	}
      66  	printf("{");
      67  	PRINT_FIELD_U(*absinfo, value);
      68  	printf(", ");
      69  	PRINT_FIELD_U(*absinfo, minimum);
      70  #if VERBOSE
      71  	printf(", ");
      72  	PRINT_FIELD_U(*absinfo, maximum);
      73  	printf(", ");
      74  	PRINT_FIELD_U(*absinfo, fuzz);
      75  	printf(", ");
      76  	PRINT_FIELD_U(*absinfo, flat);
      77  	if (sz > offsetofend(struct input_absinfo, flat)) {
      78  		if (sz >= 24) {
      79  			printf(", ");
      80  			PRINT_FIELD_U(*absinfo, resolution);
      81  
      82  			if (sz > 24)
      83  				printf(", ...");
      84  		} else {
      85  			printf(", ...");
      86  		}
      87  	}
      88  #else
      89  	printf(", ...");
      90  #endif
      91  	printf("}");
      92  }
      93  
      94  static void
      95  print_input_id(long rc, const void *ptr, const void *arg)
      96  {
      97  	const struct input_id *id = ptr;
      98  
      99  	if (rc < 0) {
     100  		printf("%p", id);
     101  		return;
     102  	}
     103  	printf("{bustype=%" PRIu16
     104  	       ", vendor=%" PRIu16
     105  	       ", product=%" PRIu16
     106  	       ", version=%" PRIu16 "}",
     107  	       id->bustype, id->vendor, id->product, id->version);
     108  }
     109  
     110  static void
     111  print_mtslots(long rc, const void *ptr, const void *arg)
     112  {
     113  	const unsigned int *buffer = ptr;
     114  	const char * const * str = arg;
     115  
     116  	if (rc < 0) {
     117  		printf("%p", buffer);
     118  		return;
     119  	}
     120  
     121  	printf("{code=%s", sprintxlat(*str, *buffer, NULL));
     122  	printf(", values=[");
     123  	for (unsigned int i = 1; str[i]; i++)
     124  		printf("%s%s", i > 1 ? ", " : "", str[i]);
     125  	printf("]}");
     126  }
     127  
     128  static void
     129  print_getbit(long rc, const void *ptr, const void *arg)
     130  {
     131  	const char * const *str = arg + sizeof(char *);
     132  #if XLAT_RAW || XLAT_VERBOSE
     133  	const unsigned long *buf = ptr;
     134  	const unsigned long buf_size = (uintptr_t) (str[-1]);
     135  #endif
     136  
     137  
     138  
     139  	if (rc <= 0) {
     140  		printf("%p", ptr);
     141  		return;
     142  	}
     143  
     144  #if !XLAT_RAW
     145  	printf("[");
     146  	for (unsigned long i = 0; str[i]; i++) {
     147  # if ! VERBOSE
     148  		if (i >= 4) {
     149  			printf(" ...");
     150  			break;
     151  		}
     152  # endif
     153  		if (i)
     154  			printf(" ");
     155  		printf("%s", str[i]);
     156  	}
     157  	printf("]");
     158  #endif /* !XLAT_RAW */
     159  
     160  #if XLAT_VERBOSE
     161  	printf(" /* ");
     162  #endif
     163  
     164  #if XLAT_RAW || XLAT_VERBOSE
     165  	printf("[");
     166  	const unsigned long cnt =
     167  		(MIN((unsigned long) rc, buf_size) + sizeof(long) - 1)
     168  		/ sizeof(long);
     169  	for (unsigned long i = 0; i < cnt; i++)
     170  		printf("%s%#lx", i ? ", " : "", buf[i]);
     171  	printf("]");
     172  #endif
     173  
     174  #if XLAT_VERBOSE
     175  	printf(" */");
     176  #endif
     177  }
     178  
     179  int
     180  main(int argc, char **argv)
     181  {
     182  	unsigned long num_skip;
     183  	long inject_retval;
     184  	bool locked = false;
     185  
     186  	if (argc == 1)
     187  		return 0;
     188  
     189  	if (argc < 3)
     190  		error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
     191  
     192  	num_skip = strtoul(argv[1], NULL, 0);
     193  	inject_retval = strtol(argv[2], NULL, 0);
     194  
     195  	if (inject_retval < 0)
     196  		error_msg_and_fail("Expected non-negative INJECT_RETVAL, "
     197  				   "but got %ld", inject_retval);
     198  
     199  	for (unsigned int i = 0; i < num_skip; i++) {
     200  		long rc = ioctl(-1, EVIOCGID, NULL);
     201  		printf("ioctl(-1, %s, NULL) = %s%s\n",
     202  		       XLAT_STR(EVIOCGID), sprintrc(rc),
     203  		       rc == inject_retval ? " (INJECTED)" : "");
     204  
     205  		if (rc != inject_retval)
     206  			continue;
     207  
     208  		locked = true;
     209  		break;
     210  	}
     211  
     212  	if (!locked)
     213  		error_msg_and_fail("Hasn't locked on ioctl(-1"
     214  				   ", EVIOCGID, NULL) returning %lu",
     215  				   inject_retval);
     216  
     217  	static const void *absinfo_sz =
     218  		(const void *) (uintptr_t) sizeof(struct input_absinfo);
     219  
     220  	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_id, id);
     221  	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_absinfo, absinfo);
     222  	TAIL_ALLOC_OBJECT_CONST_PTR(int, bad_addr_slot);
     223  
     224  	struct input_absinfo *absinfo_24 = tail_alloc(MAX(sizeof(*absinfo_24),
     225  							  24));
     226  	struct input_absinfo *absinfo_32 = tail_alloc(MAX(sizeof(*absinfo_32),
     227  							  32));
     228  
     229  	fill_memory(absinfo, sizeof(struct input_absinfo));
     230  	fill_memory(absinfo_24, 24);
     231  	fill_memory(absinfo_32, 32);
     232  
     233  	static const unsigned int mtslots[] = { ABS_MT_SLOT, 1, 3 };
     234  	static const char * const mtslots_str[] = {
     235  		"ABS_MT_SLOT", "1", "3", NULL };
     236  
     237  	/* invalid flag */
     238  	static const unsigned int invalid_mtslot[] = { -1, 1 };
     239  	static const char * const invalid_mtslot_str[] = {
     240  		""
     241  #if !XLAT_RAW && !XLAT_VERBOSE
     242  		"0xffffffff"
     243  #endif
     244  #if !XLAT_VERBOSE
     245  		" /* "
     246  #endif
     247  		"ABS_MT_???"
     248  #if !XLAT_VERBOSE
     249  		" */"
     250  #endif
     251  		, "1", NULL };
     252  
     253  	enum { ULONG_BIT = sizeof(unsigned long) * 8 };
     254  
     255  	/* set more than 4 bits */
     256  	static const unsigned long ev_more[NUM_WORDS] = {
     257  		1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED | 1 << EV_SND
     258  		| 1 << EV_PWR };
     259  	static const char * const ev_more_str_2[] = {
     260  		(char *) (uintptr_t) 4,
     261  		XLAT_KNOWN(0x3, "EV_ABS"), XLAT_KNOWN(0x4, "EV_MSC"), NULL };
     262  	static const char * const ev_more_str_3[] = {
     263  		(char *) (uintptr_t) 4,
     264  		XLAT_KNOWN(0x3, "EV_ABS"), XLAT_KNOWN(0x4, "EV_MSC"),
     265  		XLAT_KNOWN(0x11, "EV_LED"), XLAT_KNOWN(0x12, "EV_SND"),
     266  		XLAT_KNOWN(0x16, "EV_PWR"), NULL };
     267  
     268  	/* set less than 4 bits */
     269  	static const unsigned long ev_less[NUM_WORDS] = {
     270  		1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED };
     271  	static const char * const ev_less_str_2[] = {
     272  		(char *) (uintptr_t) 4,
     273  		XLAT_KNOWN(0x3, "EV_ABS"), XLAT_KNOWN(0x4, "EV_MSC"), NULL };
     274  	static const char * const ev_less_str_3[] = {
     275  		(char *) (uintptr_t) 4,
     276  		XLAT_KNOWN(0x3, "EV_ABS"), XLAT_KNOWN(0x4, "EV_MSC"),
     277  		XLAT_KNOWN(0x11, "EV_LED"), NULL };
     278  
     279  	/* set zero bit */
     280  	static const unsigned long ev_zero[NUM_WORDS] = { 0x0 };
     281  	static const char * const ev_zero_str[] = {
     282  		(char *) (uintptr_t) 1,
     283  		"", NULL };
     284  
     285  	/* KEY_MAX is 0x2ff which is greater than retval * 8 */
     286  	static const unsigned long key[NUM_WORDS] = {
     287  		1 << KEY_1 | 1 << KEY_2,
     288  		[ KEY_F12 / ULONG_BIT ] = 1 << (KEY_F12 % ULONG_BIT) };
     289  
     290  	static const char * const key_str_8[] = {
     291  		(char *) (uintptr_t) (NUM_WORDS * sizeof(long)),
     292  		XLAT_KNOWN(0x2, "KEY_1"), XLAT_KNOWN(0x3, "KEY_2"), NULL };
     293  	static const char * const key_str_16[] = {
     294  		(char *) (uintptr_t) (NUM_WORDS * sizeof(long)),
     295  		XLAT_KNOWN(0x2, "KEY_1"), XLAT_KNOWN(0x3, "KEY_2"),
     296  		XLAT_KNOWN(0x58, "KEY_F12"), NULL };
     297  
     298  	assert(sizeof(ev_more) >= (unsigned long) inject_retval);
     299  	assert(sizeof(ev_less) >= (unsigned long) inject_retval);
     300  	assert(sizeof(ev_zero) >= (unsigned long) inject_retval);
     301  	assert(sizeof(key) >= (unsigned long) inject_retval);
     302  
     303  	struct {
     304  		struct evdev_check check;
     305  		const void *ptr;
     306  	} a[] = {
     307  		{ { ARG_STR(EVIOCGID), id, print_input_id }, NULL },
     308  		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 19), "EVIOCGABS(ABS_Y)",
     309  		    absinfo, NULL }, NULL },
     310  		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 20),
     311  		    "EVIOCGABS(ABS_Y)", absinfo, print_input_absinfo },
     312  		  (const void *) (uintptr_t) 20 },
     313  		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 21),
     314  		    "EVIOCGABS(ABS_Y)", absinfo_24, print_input_absinfo },
     315  		  (const void *) (uintptr_t) 21 },
     316  		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 24),
     317  		    "EVIOCGABS(ABS_Y)", absinfo_24, print_input_absinfo },
     318  		  (const void *) (uintptr_t) 24 },
     319  		{ { _IOC(_IOC_READ, 'E', 0x40 + ABS_Y, 32),
     320  		    "EVIOCGABS(ABS_Y)", absinfo_32, print_input_absinfo },
     321  		  (const void *) (uintptr_t) 32 },
     322  		{ { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo },
     323  		  absinfo_sz},
     324  		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo },
     325  		  absinfo_sz },
     326  		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo },
     327  		  absinfo_sz },
     328  		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_more, print_getbit },
     329  			inject_retval * 8 <= EV_LED
     330  				? (const void *) &ev_more_str_2
     331  				: (const void *) &ev_more_str_3 },
     332  		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_less, print_getbit },
     333  			inject_retval * 8 <= EV_LED
     334  				? (const void *) &ev_less_str_2
     335  				: (const void *) &ev_less_str_3 },
     336  		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_zero, print_getbit }, &ev_zero_str },
     337  		{ { ARG_STR(EVIOCGBIT(EV_KEY, 0)), key, print_getbit },
     338  			inject_retval * 8 <= KEY_F12
     339  				? (const void *) &key_str_8
     340  				: (const void *) &key_str_16 },
     341  		{ { ARG_STR(EVIOCGMTSLOTS(12)), mtslots, print_mtslots }, &mtslots_str },
     342  		{ { ARG_STR(EVIOCGMTSLOTS(8)), invalid_mtslot, print_mtslots }, &invalid_mtslot_str }
     343  	};
     344  	for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) {
     345  		test_evdev(&a[i].check, a[i].ptr);
     346  	}
     347  
     348  	puts("+++ exited with 0 +++");
     349  	return 0;
     350  }