File: ioctl_perf-success.c

package info (click to toggle)
strace 5.10-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 49,332 kB
  • sloc: ansic: 113,177; sh: 8,831; makefile: 3,108; awk: 364; perl: 267; sed: 9
file content (141 lines) | stat: -rw-r--r-- 3,914 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * Check decoding of successful PERF_EVENT_IOC_{ID,QUERY_BPF} ioctls.
 *
 * Copyright (c) 2018-2020 The strace developers.
 * All rights reserved.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "tests.h"


#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>

#ifdef HAVE_LINUX_PERF_EVENT_H
# include <linux/perf_event.h>
#endif

#ifndef PERF_EVENT_IOC_ID
# define PERF_EVENT_IOC_ID			_IOR('$', 7, void *)
#endif

#ifndef PERF_EVENT_IOC_QUERY_BPF
# define PERF_EVENT_IOC_QUERY_BPF		_IOWR('$', 10, void *)

struct perf_event_query_bpf {
        uint32_t ids_len;
        uint32_t prog_cnt;
        uint32_t ids[0];
};
#endif

int
main(int argc, char **argv)
{
	static const uint64_t magic64 = 0xfacefeeddeadc0deULL;

	TAIL_ALLOC_OBJECT_CONST_PTR(uint64_t, u64_ptr);
	uint64_t *const u64_efault = u64_ptr + 1;
	uint32_t *const u32_arr = tail_alloc(sizeof(uint32_t) * 4);
	uint32_t *const u32_efault = u32_arr + 4;

	unsigned long num_skip;
	long inject_retval;
	bool locked = false;

	*u64_ptr = magic64;

	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 long i = 0; i < num_skip; i++) {
		long ret = ioctl(-1, PERF_EVENT_IOC_ID, NULL);

		printf("ioctl(-1, PERF_EVENT_IOC_ID, NULL) = %s%s\n",
		       sprintrc(ret),
		       ret == inject_retval ? " (INJECTED)" : "");

		if (ret != inject_retval)
			continue;

		locked = true;
		break;
	}

	if (!locked)
		error_msg_and_fail("Hasn't locked on ioctl(-1"
				   ", PERF_EVENT_IOC_ID, NULL) returning %lu",
				   inject_retval);

	/* PERF_EVENT_IOC_ID */
	assert(ioctl(-1, PERF_EVENT_IOC_ID, NULL) == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_ID, NULL) = %ld (INJECTED)\n",
	       inject_retval);

	assert(ioctl(-1, PERF_EVENT_IOC_ID, u64_efault) == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_ID, %p) = %ld (INJECTED)\n",
	       u64_efault, inject_retval);

	assert(ioctl(-1, PERF_EVENT_IOC_ID, u64_ptr) == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_ID, [%" PRIu64 "]) = %ld (INJECTED)\n",
	       magic64, inject_retval);

	/* PERF_EVENT_IOC_QUERY_BPF */
	assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, NULL) == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, NULL) = %ld (INJECTED)\n",
	       inject_retval);

	assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_efault)
	       == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, %p) = %ld (INJECTED)\n",
	       u32_efault, inject_retval);

	u32_arr[3] = 0xdeadbeef;
	assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_arr + 3)
	       == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, {ids_len=3735928559, ...}) "
	       "= %ld (INJECTED)\n",
	       inject_retval);

	u32_arr[2] = 0xdecaffed;
	assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_arr + 2)
	       == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, {ids_len=3737845741"
	       ", prog_cnt=3735928559, ids=%p})"
	       " = %ld (INJECTED)\n",
	       u32_efault, inject_retval);

	u32_arr[0] = 0xbadc0ded;
	u32_arr[1] = 5;
	assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_arr) == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, {ids_len=3134983661"
	       ", prog_cnt=5, ids=[3737845741, 3735928559, ... /* %p */]})"
	       " = %ld (INJECTED)\n",
	       u32_efault, inject_retval);

	u32_arr[1] = 2;
	assert(ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, u32_arr) == inject_retval);
	printf("ioctl(-1, PERF_EVENT_IOC_QUERY_BPF, {ids_len=3134983661"
	       ", prog_cnt=2, ids=[3737845741, 3735928559]})"
	       " = %ld (INJECTED)\n",
	       inject_retval);

	puts("+++ exited with 0 +++");
	return 0;
}