1 /*
2 * Check decoding of successful PERF_EVENT_IOC_{ID,QUERY_BPF} ioctls.
3 *
4 * Copyright (c) 2018-2021 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11 #include <assert.h>
12 #include <inttypes.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/ioctl.h>
17 #include <linux/perf_event.h>
18
19 int
20 main(int argc, char **argv)
21 {
22 static const uint64_t magic64 = 0xfacefeeddeadc0deULL;
23
24 TAIL_ALLOC_OBJECT_CONST_PTR(uint64_t, u64_ptr);
25 uint64_t *const u64_efault = u64_ptr + 1;
26 uint32_t *const u32_arr = tail_alloc(sizeof(uint32_t) * 4);
27 uint32_t *const u32_efault = u32_arr + 4;
28
29 unsigned long num_skip;
30 long inject_retval;
31 bool locked = false;
32
33 *u64_ptr = magic64;
34
35 if (argc == 1)
36 return 0;
37
38 if (argc < 3)
39 error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
40
41 num_skip = strtoul(argv[1], NULL, 0);
42 inject_retval = strtol(argv[2], NULL, 0);
43
44 if (inject_retval < 0)
45 error_msg_and_fail("Expected non-negative INJECT_RETVAL, "
46 "but got %ld", inject_retval);
47
48 for (unsigned long i = 0; i < num_skip; i++) {
49 long ret = ioctl(-1, PERF_EVENT_IOC_ID, NULL);
50
51 printf("ioctl(-1, PERF_EVENT_IOC_ID, NULL) = %s%s\n",
52 sprintrc(ret),
53 ret == inject_retval ? " (INJECTED)" : "");
54
55 if (ret != inject_retval)
56 continue;
57
58 locked = true;
59 break;
60 }
61
62 if (!locked)
63 error_msg_and_fail("Hasn't locked on ioctl(-1"
64 ", PERF_EVENT_IOC_ID, NULL) returning %lu",
65 inject_retval);
66
67 /* PERF_EVENT_IOC_ID */
68 assert(ioctl(-1, PERF_EVENT_IOC_ID, NULL) == inject_retval);
69 printf("ioctl(-1, PERF_EVENT_IOC_ID, NULL) = %ld (INJECTED)\n",
70 inject_retval);
71
72 assert(ioctl(-1, PERF_EVENT_IOC_ID, u64_efault) == inject_retval);
73 printf("ioctl(-1, PERF_EVENT_IOC_ID, %p) = %ld (INJECTED)\n",
74 u64_efault, inject_retval);
75
76 assert(ioctl(-1, PERF_EVENT_IOC_ID, u64_ptr) == inject_retval);
77 printf("ioctl(-1, PERF_EVENT_IOC_ID, [%" PRIu64 "]) = %ld (INJECTED)\n",
78 magic64, inject_retval);
79
80 /* PERF_EVENT_IOC_QUERY_BPF */
81 assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, NULL) == inject_retval);
82 printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, NULL) = %ld (INJECTED)\n",
83 inject_retval);
84
85 assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_efault)
86 == inject_retval);
87 printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, %p) = %ld (INJECTED)\n",
88 u32_efault, inject_retval);
89
90 u32_arr[3] = 0xdeadbeef;
91 assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_arr + 3)
92 == inject_retval);
93 printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, {ids_len=3735928559, ...}) "
94 "= %ld (INJECTED)\n",
95 inject_retval);
96
97 u32_arr[2] = 0xdecaffed;
98 assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_arr + 2)
99 == inject_retval);
100 printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, {ids_len=3737845741"
101 ", prog_cnt=3735928559, ids=%p})"
102 " = %ld (INJECTED)\n",
103 u32_efault, inject_retval);
104
105 u32_arr[0] = 0xbadc0ded;
106 u32_arr[1] = 5;
107 assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_arr) == inject_retval);
108 printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, {ids_len=3134983661"
109 ", prog_cnt=5, ids=[3737845741, 3735928559, ... /* %p */]})"
110 " = %ld (INJECTED)\n",
111 u32_efault, inject_retval);
112
113 u32_arr[1] = 2;
114 assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_arr) == inject_retval);
115 printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, {ids_len=3134983661"
116 ", prog_cnt=2, ids=[3737845741, 3735928559]})"
117 " = %ld (INJECTED)\n",
118 inject_retval);
119
120 puts("+++ exited with 0 +++");
121 return 0;
122 }