• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Check bpf syscall decoding.
3  *
4  * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
5  * Copyright (c) 2015-2018 The strace developers.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "tests.h"
32 
33 #include <stddef.h>
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <string.h>
37 #include <unistd.h>
38 
39 #include <asm/unistd.h>
40 #include "scno.h"
41 
42 #ifdef HAVE_LINUX_BPF_H
43 # include <linux/bpf.h>
44 #endif
45 
46 #include "bpf_attr.h"
47 #include "print_fields.h"
48 
49 #include "xlat.h"
50 #include "xlat/bpf_commands.h"
51 
52 #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4
53 # define BIG_ADDR(addr64_, addr32_) addr64_
54 # define BIG_ADDR_MAYBE(addr_)
55 #elif defined __arm__ || defined __i386__ || defined __mips__ \
56    || defined __powerpc__ || defined __riscv__ || defined __s390__ \
57    || defined __sparc__ || defined __tile__
58 # define BIG_ADDR(addr64_, addr32_) addr64_ " or " addr32_
59 # define BIG_ADDR_MAYBE(addr_) addr_ " or "
60 #else
61 # define BIG_ADDR(addr64_, addr32_) addr32_
62 # define BIG_ADDR_MAYBE(addr_)
63 #endif
64 
65 #ifndef HAVE_STRUCT_BPF_INSN
66 struct bpf_insn {
67 	uint8_t	code;
68 	uint8_t	dst_reg:4;
69 	uint8_t	src_reg:4;
70 	int16_t	off;
71 	int32_t	imm;
72 };
73 #endif
74 
75 #define BPF_ATTR_DATA_FIELD(cmd_) struct cmd_ ## _struct cmd_ ## _data
76 
77 union bpf_attr_data {
78 	BPF_ATTR_DATA_FIELD(BPF_MAP_CREATE);
79 	BPF_ATTR_DATA_FIELD(BPF_MAP_LOOKUP_ELEM);
80 	BPF_ATTR_DATA_FIELD(BPF_MAP_UPDATE_ELEM);
81 	BPF_ATTR_DATA_FIELD(BPF_MAP_DELETE_ELEM);
82 	BPF_ATTR_DATA_FIELD(BPF_MAP_GET_NEXT_KEY);
83 	BPF_ATTR_DATA_FIELD(BPF_PROG_LOAD);
84 	BPF_ATTR_DATA_FIELD(BPF_OBJ_PIN);
85 	BPF_ATTR_DATA_FIELD(BPF_PROG_ATTACH);
86 	BPF_ATTR_DATA_FIELD(BPF_PROG_DETACH);
87 	BPF_ATTR_DATA_FIELD(BPF_PROG_TEST_RUN);
88 	BPF_ATTR_DATA_FIELD(BPF_PROG_GET_NEXT_ID);
89 	BPF_ATTR_DATA_FIELD(BPF_PROG_GET_FD_BY_ID);
90 	BPF_ATTR_DATA_FIELD(BPF_MAP_GET_FD_BY_ID);
91 	BPF_ATTR_DATA_FIELD(BPF_OBJ_GET_INFO_BY_FD);
92 	BPF_ATTR_DATA_FIELD(BPF_PROG_QUERY);
93 	BPF_ATTR_DATA_FIELD(BPF_RAW_TRACEPOINT_OPEN);
94 	char char_data[256];
95 };
96 
97 struct bpf_attr_check {
98 	union bpf_attr_data data;
99 	size_t size;
100 	const char *str;
101 	void (*init_fn)(struct bpf_attr_check *check);
102 	void (*print_fn)(const struct bpf_attr_check *check,
103 			 unsigned long addr);
104 };
105 
106 struct bpf_check {
107 	kernel_ulong_t cmd;
108 	const char *cmd_str;
109 	const struct bpf_attr_check *checks;
110 	size_t count;
111 };
112 
113 static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL;
114 static const char *errstr;
115 static unsigned int sizeof_attr = sizeof(union bpf_attr_data);
116 static unsigned int page_size;
117 static unsigned long end_of_page;
118 
119 static long
sys_bpf(kernel_ulong_t cmd,kernel_ulong_t attr,kernel_ulong_t size)120 sys_bpf(kernel_ulong_t cmd, kernel_ulong_t attr, kernel_ulong_t size)
121 {
122 	long rc = syscall(__NR_bpf, cmd, attr, size);
123 
124 	errstr = sprintrc(rc);
125 
126 #ifdef INJECT_RETVAL
127 	if (rc != INJECT_RETVAL)
128 		error_msg_and_fail("Got a return value of %ld != %d",
129 				   rc, INJECT_RETVAL);
130 
131 	static char inj_errstr[4096];
132 
133 	snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
134 	errstr = inj_errstr;
135 #endif
136 
137 	return rc;
138 }
139 
140 #if VERBOSE
141 # define print_extra_data(addr_, offs_, size_) \
142 	do { \
143 		printf("/* bytes %u..%u */ ", (offs_), (size_) + (offs_) - 1); \
144 		print_quoted_hex((addr_) + (offs_), (size_)); \
145 	} while (0)
146 #else
147 # define print_extra_data(addr_, offs_, size_) printf("...")
148 #endif
149 
150 static void
print_bpf_attr(const struct bpf_attr_check * check,unsigned long addr)151 print_bpf_attr(const struct bpf_attr_check *check, unsigned long addr)
152 {
153 	if (check->print_fn)
154 		check->print_fn(check, addr);
155 	else
156 		printf("%s", check->str);
157 }
158 
159 static void
test_bpf(const struct bpf_check * cmd_check)160 test_bpf(const struct bpf_check *cmd_check)
161 {
162 	const struct bpf_attr_check *check = 0;
163 	const union bpf_attr_data *data = 0;
164 	unsigned int offset = 0;
165 
166 	/* zero addr */
167 	sys_bpf(cmd_check->cmd, 0, long_bits | sizeof(union bpf_attr_data));
168 	printf("bpf(%s, NULL, %u) = %s\n",
169 	       cmd_check->cmd_str, sizeof_attr, errstr);
170 
171 	/* zero size */
172 	unsigned long addr = end_of_page - sizeof_attr;
173 	sys_bpf(cmd_check->cmd, addr, long_bits);
174 	printf("bpf(%s, %#lx, 0) = %s\n",
175 	       cmd_check->cmd_str, addr, errstr);
176 
177 	for (size_t i = 0; i < cmd_check->count; i++) {
178 		check = &cmd_check->checks[i];
179 		if (check->init_fn)
180 			check->init_fn((struct bpf_attr_check *) check);
181 		data = &check->data;
182 		offset = check->size;
183 
184 		addr = end_of_page - offset;
185 		memcpy((void *) addr, data, offset);
186 
187 		/* starting piece of bpf_attr_data */
188 		sys_bpf(cmd_check->cmd, addr, offset);
189 		printf("bpf(%s, {", cmd_check->cmd_str);
190 		print_bpf_attr(check, addr);
191 		printf("}, %u) = %s\n", offset, errstr);
192 
193 		/* short read of the starting piece */
194 		sys_bpf(cmd_check->cmd, addr + 1, offset);
195 		printf("bpf(%s, %#lx, %u) = %s\n",
196 		       cmd_check->cmd_str, addr + 1, offset, errstr);
197 	}
198 
199 	if (offset < sizeof_attr) {
200 		/* short read of the whole bpf_attr_data */
201 		memcpy((void *) end_of_page - sizeof_attr + 1, data, offset);
202 		addr = end_of_page - sizeof_attr + 1;
203 		memset((void *) addr + offset, 0, sizeof_attr - offset - 1);
204 		sys_bpf(cmd_check->cmd, addr, sizeof_attr);
205 		printf("bpf(%s, %#lx, %u) = %s\n",
206 		       cmd_check->cmd_str, addr, sizeof_attr, errstr);
207 
208 		/* the whole bpf_attr_data */
209 		memcpy((void *) end_of_page - sizeof_attr, data, offset);
210 		addr = end_of_page - sizeof_attr;
211 		memset((void *) addr + offset, 0, sizeof_attr - offset);
212 		sys_bpf(cmd_check->cmd, addr, sizeof_attr);
213 		printf("bpf(%s, {", cmd_check->cmd_str);
214 		print_bpf_attr(check, addr);
215 		printf("}, %u) = %s\n", sizeof_attr, errstr);
216 
217 		/* non-zero bytes after the relevant part */
218 		fill_memory_ex((void *) addr + offset,
219 			       sizeof_attr - offset, '0', 10);
220 		sys_bpf(cmd_check->cmd, addr, sizeof_attr);
221 		printf("bpf(%s, {", cmd_check->cmd_str);
222 		print_bpf_attr(check, addr);
223 		printf(", ");
224 		print_extra_data((char *) addr, offset,
225 				 sizeof_attr - offset);
226 		printf("}, %u) = %s\n", sizeof_attr, errstr);
227 	}
228 
229 	/* short read of the whole page */
230 	memcpy((void *) end_of_page - page_size + 1, data, offset);
231 	addr = end_of_page - page_size + 1;
232 	memset((void *) addr + offset, 0, page_size - offset - 1);
233 	sys_bpf(cmd_check->cmd, addr, page_size);
234 	printf("bpf(%s, %#lx, %u) = %s\n",
235 	       cmd_check->cmd_str, addr, page_size, errstr);
236 
237 	/* the whole page */
238 	memcpy((void *) end_of_page - page_size, data, offset);
239 	addr = end_of_page - page_size;
240 	memset((void *) addr + offset, 0, page_size - offset);
241 	sys_bpf(cmd_check->cmd, addr, page_size);
242 	printf("bpf(%s, {", cmd_check->cmd_str);
243 	print_bpf_attr(check, addr);
244 	printf("}, %u) = %s\n", page_size, errstr);
245 
246 	/* non-zero bytes after the whole bpf_attr_data */
247 	fill_memory_ex((void *) addr + offset,
248 		       page_size - offset, '0', 10);
249 	sys_bpf(cmd_check->cmd, addr, page_size);
250 	printf("bpf(%s, {", cmd_check->cmd_str);
251 	print_bpf_attr(check, addr);
252 	printf(", ");
253 	print_extra_data((char *) addr, offset,
254 			 page_size - offset);
255 	printf("}, %u) = %s\n", page_size, errstr);
256 
257 	/* more than a page */
258 	sys_bpf(cmd_check->cmd, addr, page_size + 1);
259 	printf("bpf(%s, %#lx, %u) = %s\n",
260 	       cmd_check->cmd_str, addr, page_size + 1, errstr);
261 }
262 
263 static void
init_BPF_MAP_CREATE_attr7(struct bpf_attr_check * check)264 init_BPF_MAP_CREATE_attr7(struct bpf_attr_check *check)
265 {
266 	struct BPF_MAP_CREATE_struct *attr = &check->data.BPF_MAP_CREATE_data;
267 	attr->map_ifindex = ifindex_lo();
268 }
269 
270 static struct bpf_attr_check BPF_MAP_CREATE_checks[] = {
271 	{
272 		.data = { .BPF_MAP_CREATE_data = { .map_type = 2 } },
273 		.size = offsetofend(struct BPF_MAP_CREATE_struct, map_type),
274 		.str = "map_type=BPF_MAP_TYPE_ARRAY, key_size=0, value_size=0"
275 		       ", max_entries=0"
276 	},
277 	{ /* 1 */
278 		.data = { .BPF_MAP_CREATE_data = {
279 			.map_type = 20,
280 			.key_size = 4,
281 			.value_size = 8,
282 			.max_entries = 256,
283 			.map_flags = 63,
284 			.inner_map_fd = -1,
285 			.numa_node = 3141592653,
286 			.map_name = "0123456789abcde",
287 		} },
288 		.size = offsetof(struct BPF_MAP_CREATE_struct, map_name) + 8,
289 		.str = "map_type=BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, key_size=4"
290 		       ", value_size=8, max_entries=256"
291 		       ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NO_COMMON_LRU"
292 				   "|BPF_F_NUMA_NODE|BPF_F_RDONLY|BPF_F_WRONLY"
293 				   "|BPF_F_STACK_BUILD_ID"
294 		       ", inner_map_fd=-1"
295 		       ", numa_node=3141592653"
296 		       ", map_name=\"0123456\"...",
297 
298 	},
299 	{ /* 2 */
300 		.data = { .BPF_MAP_CREATE_data = {
301 			.map_type = 21,
302 			.key_size = 0xface1e55,
303 			.value_size = 0xbadc0ded,
304 			.max_entries = 0xbeefcafe,
305 			.map_flags = 0xffffffc0,
306 			.inner_map_fd = 2718281828,
307 			.numa_node = -1,
308 			.map_name = "",
309 			.map_ifindex = 3141592653,
310 		} },
311 		.size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
312 		.str = "map_type=0x15 /* BPF_MAP_TYPE_??? */"
313 		       ", key_size=4207812181, value_size=3134983661"
314 		       ", max_entries=3203386110"
315 		       ", map_flags=0xffffffc0 /* BPF_F_??? */"
316 		       ", inner_map_fd=-1576685468"
317 		       ", map_name=\"\", map_ifindex=3141592653",
318 
319 	},
320 	{ /* 3 */
321 		.data = { .BPF_MAP_CREATE_data = {
322 			.map_type = 0xdeadf00d,
323 			.key_size = 0xface1e55,
324 			.value_size = 0xbadc0ded,
325 			.max_entries = 0xbeefcafe,
326 			.map_flags = 0xc0dedead,
327 			.inner_map_fd = 2718281828,
328 			.numa_node = -1,
329 		} },
330 		.size = offsetofend(struct BPF_MAP_CREATE_struct, map_flags),
331 		.str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
332 		       ", key_size=4207812181, value_size=3134983661"
333 		       ", max_entries=3203386110"
334 		       ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
335 				   "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
336 				   "|0xc0dede80",
337 	},
338 	{ /* 4 */
339 		.data = { .BPF_MAP_CREATE_data = {
340 			.map_type = 0xdeadf00d,
341 			.key_size = 0xface1e55,
342 			.value_size = 0xbadc0ded,
343 			.max_entries = 0xbeefcafe,
344 			.map_flags = 0xc0dedead,
345 			.inner_map_fd = 2718281828,
346 			.numa_node = -1,
347 		} },
348 		.size = offsetofend(struct BPF_MAP_CREATE_struct, inner_map_fd),
349 		.str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
350 		       ", key_size=4207812181, value_size=3134983661"
351 		       ", max_entries=3203386110"
352 		       ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
353 				   "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
354 				   "|0xc0dede80"
355 		       ", inner_map_fd=-1576685468",
356 	},
357 	{ /* 5 */
358 		.data = { .BPF_MAP_CREATE_data = {
359 			.map_type = 0xdeadf00d,
360 			.key_size = 0xface1e55,
361 			.value_size = 0xbadc0ded,
362 			.max_entries = 0xbeefcafe,
363 			.map_flags = 0xc0dedead,
364 			.inner_map_fd = 2718281828,
365 			.numa_node = -1,
366 		} },
367 		.size = offsetofend(struct BPF_MAP_CREATE_struct, numa_node),
368 		.str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
369 		       ", key_size=4207812181, value_size=3134983661"
370 		       ", max_entries=3203386110"
371 		       ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
372 				   "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
373 				   "|0xc0dede80"
374 		       ", inner_map_fd=-1576685468"
375 		       ", numa_node=4294967295 /* NUMA_NO_NODE */",
376 	},
377 	{ /* 6 */
378 		.data = { .BPF_MAP_CREATE_data = {
379 			.map_type = 0xdeadf00d,
380 			.key_size = 0xface1e55,
381 			.value_size = 0xbadc0ded,
382 			.max_entries = 0xbeefcafe,
383 			.map_flags = 0xc0dedead,
384 			.inner_map_fd = 2718281828,
385 			.numa_node = -1,
386 			.map_name = "fedcba9876543210",
387 		} },
388 		.size = offsetofend(struct BPF_MAP_CREATE_struct, map_name),
389 		.str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
390 		       ", key_size=4207812181, value_size=3134983661"
391 		       ", max_entries=3203386110"
392 		       ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
393 				   "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
394 				   "|0xc0dede80"
395 		       ", inner_map_fd=-1576685468"
396 		       ", numa_node=4294967295 /* NUMA_NO_NODE */"
397 		       ", map_name=\"fedcba987654321\"...",
398 	},
399 	{ /* 7 */
400 		.data = { .BPF_MAP_CREATE_data = {
401 			.map_type = 0xdeadf00d,
402 			.key_size = 0xface1e55,
403 			.value_size = 0xbadc0ded,
404 			.max_entries = 0xbeefcafe,
405 			.map_flags = 0xc0dedead,
406 			.inner_map_fd = 2718281828,
407 			.numa_node = -1,
408 			.map_name = "0123456789abcde",
409 		} },
410 		.size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
411 		.str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
412 		       ", key_size=4207812181, value_size=3134983661"
413 		       ", max_entries=3203386110"
414 		       ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
415 				   "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
416 				   "|0xc0dede80"
417 		       ", inner_map_fd=-1576685468"
418 		       ", numa_node=4294967295 /* NUMA_NO_NODE */"
419 		       ", map_name=\"0123456789abcde\""
420 		       ", map_ifindex=" IFINDEX_LO_STR,
421 		.init_fn = init_BPF_MAP_CREATE_attr7,
422 	},
423 };
424 
425 static const struct bpf_attr_check BPF_MAP_LOOKUP_ELEM_checks[] = {
426 	{
427 		.data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1 } },
428 		.size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, map_fd),
429 		.str = "map_fd=-1, key=NULL, value=NULL"
430 	},
431 	{
432 		.data = { .BPF_MAP_LOOKUP_ELEM_data = {
433 			.map_fd = -1,
434 			.key = 0xdeadbeef,
435 			.value = 0xbadc0ded
436 		} },
437 		.size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, value),
438 		.str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
439 	}
440 };
441 
442 static const struct bpf_attr_check BPF_MAP_UPDATE_ELEM_checks[] = {
443 	{
444 		.data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1 } },
445 		.size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, map_fd),
446 		.str = "map_fd=-1, key=NULL, value=NULL, flags=BPF_ANY"
447 	},
448 	{
449 		.data = { .BPF_MAP_UPDATE_ELEM_data = {
450 			.map_fd = -1,
451 			.key = 0xdeadbeef,
452 			.value = 0xbadc0ded,
453 			.flags = 2
454 		} },
455 		.size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags),
456 		.str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
457 		       ", flags=BPF_EXIST"
458 	}
459 };
460 
461 static const struct bpf_attr_check BPF_MAP_DELETE_ELEM_checks[] = {
462 	{
463 		.data = { .BPF_MAP_DELETE_ELEM_data = { .map_fd = -1 } },
464 		.size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, map_fd),
465 		.str = "map_fd=-1, key=NULL"
466 	},
467 	{
468 		.data = { .BPF_MAP_DELETE_ELEM_data = {
469 			.map_fd = -1,
470 			.key = 0xdeadbeef
471 		} },
472 		.size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, key),
473 		.str = "map_fd=-1, key=0xdeadbeef"
474 	}
475 };
476 
477 static const struct bpf_attr_check BPF_MAP_GET_NEXT_KEY_checks[] = {
478 	{
479 		.data = { .BPF_MAP_GET_NEXT_KEY_data = { .map_fd = -1 } },
480 		.size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, map_fd),
481 		.str = "map_fd=-1, key=NULL, next_key=NULL"
482 	},
483 	{
484 		.data = { .BPF_MAP_GET_NEXT_KEY_data = {
485 			.map_fd = -1,
486 			.key = 0xdeadbeef,
487 			.next_key = 0xbadc0ded
488 		} },
489 		.size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, next_key),
490 		.str = "map_fd=-1, key=0xdeadbeef, next_key=0xbadc0ded"
491 	}
492 };
493 
494 static const struct bpf_insn insns[] = {
495 	{
496 		.code = 0x95,
497 		.dst_reg = 10,
498 		.src_reg = 11,
499 		.off = 0xdead,
500 		.imm = 0xbadc0ded,
501 	},
502 };
503 static const char license[] = "GPL";
504 static const char pathname[] = "/sys/fs/bpf/foo/bar";
505 
506 static char *log_buf;
507 /*
508  * This has to be a macro, otherwise the compiler complains that
509  * initializer element is not constant.
510  */
511 #define log_buf_size 4096U
512 
513 static inline char *
get_log_buf(void)514 get_log_buf(void)
515 {
516 	if (!log_buf)
517 		log_buf = tail_alloc(log_buf_size);
518 	return log_buf;
519 }
520 
521 static inline char *
get_log_buf_tail(void)522 get_log_buf_tail(void)
523 {
524 	return get_log_buf() + log_buf_size;
525 }
526 
527 #if VERBOSE
528 # define INSNS_FMT \
529 	"[{code=BPF_JMP|BPF_K|BPF_EXIT, dst_reg=BPF_REG_10" \
530 	", src_reg=0xb /* BPF_REG_??? */, off=%d, imm=%#x}]"
531 # define INSNS_ARG insns[0].off, insns[0].imm
532 #else
533 # define INSNS_FMT "%p"
534 # define INSNS_ARG insns
535 #endif
536 
537 static void
init_BPF_PROG_LOAD_attr3(struct bpf_attr_check * check)538 init_BPF_PROG_LOAD_attr3(struct bpf_attr_check *check)
539 {
540 	struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
541 
542 	attr->insns = (uintptr_t) insns;
543 	attr->license = (uintptr_t) license;
544 	attr->log_buf = (uintptr_t) get_log_buf_tail();
545 }
546 
547 static void
print_BPF_PROG_LOAD_attr3(const struct bpf_attr_check * check,unsigned long addr)548 print_BPF_PROG_LOAD_attr3(const struct bpf_attr_check *check, unsigned long addr)
549 {
550 	printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u"
551 	       ", insns=" INSNS_FMT ", license=\"%s\", log_level=2718281828"
552 	       ", log_size=%u, log_buf=%p"
553 	       ", kern_version=KERNEL_VERSION(51966, 240, 13)"
554 	       ", prog_flags=0x2 /* BPF_F_??? */"
555 	       ", prog_name=\"0123456789abcde\"..., prog_ifindex=3203399405",
556 	       (unsigned int) ARRAY_SIZE(insns), INSNS_ARG, license,
557 	       log_buf_size, get_log_buf_tail());
558 }
559 
560 static void
init_BPF_PROG_LOAD_attr4(struct bpf_attr_check * check)561 init_BPF_PROG_LOAD_attr4(struct bpf_attr_check *check)
562 {
563 	struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
564 
565 	attr->insns = (uintptr_t) insns;
566 	attr->license = (uintptr_t) license;
567 	attr->log_buf = (uintptr_t) get_log_buf();
568 	attr->prog_ifindex = ifindex_lo();
569 
570 	strncpy(log_buf, "log test", 9);
571 }
572 
573 static void
print_BPF_PROG_LOAD_attr4(const struct bpf_attr_check * check,unsigned long addr)574 print_BPF_PROG_LOAD_attr4(const struct bpf_attr_check *check, unsigned long addr)
575 {
576 	printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=" INSNS_FMT
577 	       ", license=\"%s\", log_level=2718281828, log_size=4"
578 	       ", log_buf=\"log \"..."
579 	       ", kern_version=KERNEL_VERSION(51966, 240, 13)"
580 	       ", prog_flags=BPF_F_STRICT_ALIGNMENT|0x2"
581 	       ", prog_name=\"0123456789abcde\"..., prog_ifindex=%s"
582 	       ", expected_attach_type=BPF_CGROUP_INET6_BIND",
583 	       (unsigned int) ARRAY_SIZE(insns), INSNS_ARG,
584 	       license, IFINDEX_LO_STR);
585 }
586 
587 static struct bpf_attr_check BPF_PROG_LOAD_checks[] = {
588 	{
589 		.data = { .BPF_PROG_LOAD_data = { .prog_type = 1 } },
590 		.size = offsetofend(struct BPF_PROG_LOAD_struct, prog_type),
591 		.str = "prog_type=BPF_PROG_TYPE_SOCKET_FILTER"
592 		       ", insn_cnt=0, insns=NULL, license=NULL"
593 	},
594 	{ /* 1 */
595 		.data = { .BPF_PROG_LOAD_data = {
596 			.prog_type = 21,
597 			.insn_cnt = 0xbadc0ded,
598 			.insns = 0,
599 			.license = 0,
600 			.log_level = 42,
601 			.log_size = 3141592653U,
602 			.log_buf = 0,
603 			.kern_version = 0xcafef00d,
604 			.prog_flags = 0,
605 		} },
606 		.size = offsetofend(struct BPF_PROG_LOAD_struct, prog_flags),
607 		.str = "prog_type=0x15 /* BPF_PROG_TYPE_??? */"
608 		       ", insn_cnt=3134983661, insns=NULL, license=NULL"
609 		       ", log_level=42, log_size=3141592653, log_buf=NULL"
610 		       ", kern_version=KERNEL_VERSION(51966, 240, 13)"
611 		       ", prog_flags=0",
612 	},
613 	{ /* 2 */
614 		.data = { .BPF_PROG_LOAD_data = {
615 			.prog_type = 20,
616 			.insn_cnt = 0xbadc0ded,
617 			.insns = 0xffffffff00000000,
618 			.license = 0xffffffff00000000,
619 			.log_level = 2718281828U,
620 			.log_size = log_buf_size,
621 			.log_buf = 0xffffffff00000000,
622 			.kern_version = 0xcafef00d,
623 			.prog_flags = 1,
624 			.prog_name = "fedcba987654321",
625 		} },
626 		.size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name),
627 		.str = "prog_type=BPF_PROG_TYPE_SK_REUSEPORT"
628 		       ", insn_cnt=3134983661"
629 		       ", insns=" BIG_ADDR("0xffffffff00000000", "NULL")
630 		       ", license=" BIG_ADDR("0xffffffff00000000", "NULL")
631 		       ", log_level=2718281828, log_size=4096"
632 		       ", log_buf=" BIG_ADDR("0xffffffff00000000", "NULL")
633 		       ", kern_version=KERNEL_VERSION(51966, 240, 13)"
634 		       ", prog_flags=BPF_F_STRICT_ALIGNMENT"
635 		       ", prog_name=\"fedcba987654321\"",
636 	},
637 	{ /* 3 */
638 		.data = { .BPF_PROG_LOAD_data = {
639 			.prog_type = 1,
640 			.insn_cnt = ARRAY_SIZE(insns),
641 			.log_level = 2718281828U,
642 			.log_size = log_buf_size,
643 			.kern_version = 0xcafef00d,
644 			.prog_flags = 2,
645 			.prog_name = "0123456789abcdef",
646 			.prog_ifindex = 0xbeeffeed,
647 		} },
648 		.size = offsetofend(struct BPF_PROG_LOAD_struct, prog_ifindex),
649 		.init_fn = init_BPF_PROG_LOAD_attr3,
650 		.print_fn = print_BPF_PROG_LOAD_attr3
651 	},
652 	{ /* 4 */
653 		.data = { .BPF_PROG_LOAD_data = {
654 			.prog_type = 0,
655 			.insn_cnt = ARRAY_SIZE(insns),
656 			.log_level = 2718281828U,
657 			.log_size = 4,
658 			.kern_version = 0xcafef00d,
659 			.prog_flags = 3,
660 			.prog_name = "0123456789abcdef",
661 			.expected_attach_type = 9,
662 		} },
663 		.size = offsetofend(struct BPF_PROG_LOAD_struct,
664 				    expected_attach_type),
665 		.init_fn = init_BPF_PROG_LOAD_attr4,
666 		.print_fn = print_BPF_PROG_LOAD_attr4
667 	},
668 };
669 
670 static void
init_BPF_OBJ_PIN_attr(struct bpf_attr_check * check)671 init_BPF_OBJ_PIN_attr(struct bpf_attr_check *check)
672 {
673 	struct BPF_OBJ_PIN_struct *attr = &check->data.BPF_OBJ_PIN_data;
674 	attr->pathname = (uintptr_t) pathname;
675 }
676 
677 static struct bpf_attr_check BPF_OBJ_PIN_checks[] = {
678 	{
679 		.data = { .BPF_OBJ_PIN_data = { .pathname = 0 } },
680 		.size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
681 		.str = "pathname=NULL, bpf_fd=0"
682 	},
683 	{
684 		.data = { .BPF_OBJ_PIN_data = {
685 			.pathname = 0xFFFFFFFFFFFFFFFFULL
686 		} },
687 		.size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
688 		.str = "pathname=" BIG_ADDR("0xffffffffffffffff", "0xffffffff")
689 		       ", bpf_fd=0",
690 	},
691 	{
692 		.data = { .BPF_OBJ_PIN_data = { .bpf_fd = -1 } },
693 		.size = offsetofend(struct BPF_OBJ_PIN_struct, bpf_fd),
694 		.init_fn = init_BPF_OBJ_PIN_attr,
695 		.str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
696 	},
697 	{
698 		.data = { .BPF_OBJ_PIN_data = {
699 			.bpf_fd = -1,
700 			.file_flags = 0x18
701 		} },
702 		.size = offsetofend(struct BPF_OBJ_PIN_struct, file_flags),
703 		.init_fn = init_BPF_OBJ_PIN_attr,
704 		.str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
705 		       ", file_flags=BPF_F_RDONLY|BPF_F_WRONLY"
706 	}
707 };
708 
709 #define BPF_OBJ_GET_checks BPF_OBJ_PIN_checks
710 
711 static const struct bpf_attr_check BPF_PROG_ATTACH_checks[] = {
712 	{
713 		.data = { .BPF_PROG_ATTACH_data = { .target_fd = -1 } },
714 		.size = offsetofend(struct BPF_PROG_ATTACH_struct, target_fd),
715 		.str = "target_fd=-1, attach_bpf_fd=0"
716 		       ", attach_type=BPF_CGROUP_INET_INGRESS, attach_flags=0"
717 	},
718 	{
719 		.data = { .BPF_PROG_ATTACH_data = {
720 			.target_fd = -1,
721 			.attach_bpf_fd = -2,
722 			.attach_type = 2,
723 			.attach_flags = 1
724 		} },
725 		.size = offsetofend(struct BPF_PROG_ATTACH_struct, attach_flags),
726 		.str = "target_fd=-1, attach_bpf_fd=-2"
727 		       ", attach_type=BPF_CGROUP_INET_SOCK_CREATE"
728 		       ", attach_flags=BPF_F_ALLOW_OVERRIDE"
729 	}
730 };
731 
732 
733 static const struct bpf_attr_check BPF_PROG_DETACH_checks[] = {
734 	{
735 		.data = { .BPF_PROG_DETACH_data = { .target_fd = -1 } },
736 		.size = offsetofend(struct BPF_PROG_DETACH_struct, target_fd),
737 		.str = "target_fd=-1, attach_type=BPF_CGROUP_INET_INGRESS"
738 	},
739 	{
740 		.data = { .BPF_PROG_DETACH_data = {
741 			.target_fd = -1,
742 			.attach_type = 2
743 		} },
744 		.size = offsetofend(struct BPF_PROG_DETACH_struct, attach_type),
745 		.str = "target_fd=-1, attach_type=BPF_CGROUP_INET_SOCK_CREATE"
746 	}
747 };
748 
749 static const struct bpf_attr_check BPF_PROG_TEST_RUN_checks[] = {
750 	{
751 		.data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1 } },
752 		.size = offsetofend(struct BPF_PROG_TEST_RUN_struct, prog_fd),
753 		.str = "test={prog_fd=-1, retval=0, data_size_in=0"
754 		       ", data_size_out=0, data_in=NULL, data_out=NULL"
755 		       ", repeat=0, duration=0}"
756 	},
757 	{
758 		.data = { .BPF_PROG_TEST_RUN_data = {
759 			.prog_fd = -1,
760 			.retval = 0xfac1fed2,
761 			.data_size_in = 0xfac3fed4,
762 			.data_size_out = 0xfac5fed6,
763 			.data_in = (uint64_t) 0xfacef11dbadc2dedULL,
764 			.data_out = (uint64_t) 0xfacef33dbadc4dedULL,
765 			.repeat = 0xfac7fed8,
766 			.duration = 0xfac9feda
767 		} },
768 		.size = offsetofend(struct BPF_PROG_TEST_RUN_struct, duration),
769 		.str = "test={prog_fd=-1, retval=4207017682"
770 		       ", data_size_in=4207148756, data_size_out=4207279830"
771 		       ", data_in=0xfacef11dbadc2ded"
772 		       ", data_out=0xfacef33dbadc4ded"
773 		       ", repeat=4207410904, duration=4207541978}"
774 	}
775 };
776 
777 static const struct bpf_attr_check BPF_PROG_GET_NEXT_ID_checks[] = {
778 	{
779 		.data = { .BPF_PROG_GET_NEXT_ID_data = {
780 			.start_id = 0xdeadbeef
781 		} },
782 		.size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, start_id),
783 		.str = "start_id=3735928559, next_id=0"
784 	},
785 	{
786 		.data = { .BPF_PROG_GET_NEXT_ID_data = {
787 			.start_id = 0xdeadbeef
788 		} },
789 		.size = 1,
790 		.str = "start_id="
791 #if WORDS_BIGENDIAN
792 		       "3724541952"	/* 0xde000000 */
793 #else
794 		       "239"		/* 0x000000ef */
795 #endif
796 		       ", next_id=0"
797 	},
798 	{
799 		.data = { .BPF_PROG_GET_NEXT_ID_data = {
800 			.start_id = 0xbadc0ded,
801 			.next_id = 0xcafef00d
802 		} },
803 		.size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, next_id),
804 		.str = "start_id=3134983661, next_id=3405705229"
805 	},
806 	{
807 		.data = { .BPF_PROG_GET_NEXT_ID_data = {
808 			.start_id = 0xbadc0ded,
809 			.next_id = 0xcafef00d,
810 			.open_flags = 0xffffff27
811 		} },
812 		.size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, open_flags),
813 		.str = "start_id=3134983661, next_id=3405705229"
814 		       ", open_flags=0xffffff27 /* BPF_F_??? */"
815 	}
816 };
817 
818 #define BPF_MAP_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks
819 
820 static const struct bpf_attr_check BPF_PROG_GET_FD_BY_ID_checks[] = {
821 	{
822 		.data = { .BPF_PROG_GET_FD_BY_ID_data = {
823 			.prog_id = 0xdeadbeef
824 		} },
825 		.size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, prog_id),
826 		.str = "prog_id=3735928559, next_id=0"
827 	},
828 	{
829 		.data = { .BPF_PROG_GET_FD_BY_ID_data = {
830 			.prog_id = 0xbadc0ded,
831 			.next_id = 0xcafef00d
832 		} },
833 		.size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, next_id),
834 		.str = "prog_id=3134983661, next_id=3405705229"
835 	},
836 	{
837 		.data = { .BPF_PROG_GET_FD_BY_ID_data = {
838 			.prog_id = 0xbadc0ded,
839 			.next_id = 0xcafef00d,
840 			.open_flags = 0xffffff27
841 		} },
842 		.size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, open_flags),
843 		.str = "prog_id=3134983661, next_id=3405705229"
844 		       ", open_flags=0xffffff27 /* BPF_F_??? */"
845 	}
846 };
847 
848 static const struct bpf_attr_check BPF_MAP_GET_FD_BY_ID_checks[] = {
849 	{
850 		.data = { .BPF_MAP_GET_FD_BY_ID_data = {
851 			.map_id = 0xdeadbeef
852 		} },
853 		.size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, map_id),
854 		.str = "map_id=3735928559, next_id=0"
855 	},
856 	{
857 		.data = { .BPF_MAP_GET_FD_BY_ID_data = {
858 			.map_id = 0xbadc0ded,
859 			.next_id = 0xcafef00d
860 		} },
861 		.size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, next_id),
862 		.str = "map_id=3134983661, next_id=3405705229"
863 	},
864 	{
865 		.data = { .BPF_MAP_GET_FD_BY_ID_data = {
866 			.map_id = 0xbadc0ded,
867 			.next_id = 0xcafef00d,
868 			.open_flags = 0xffffff27
869 		} },
870 		.size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags),
871 		.str = "map_id=3134983661, next_id=3405705229"
872 		       ", open_flags=0xffffff27 /* BPF_F_??? */"
873 	}
874 };
875 
876 static const struct bpf_attr_check BPF_OBJ_GET_INFO_BY_FD_checks[] = {
877 	{
878 		.data = { .BPF_OBJ_GET_INFO_BY_FD_data = { .bpf_fd = -1 } },
879 		.size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, bpf_fd),
880 		.str = "info={bpf_fd=-1, info_len=0, info=NULL}"
881 	},
882 	{
883 		.data = { .BPF_OBJ_GET_INFO_BY_FD_data = {
884 			.bpf_fd = -1,
885 			.info_len = 0xdeadbeef,
886 			.info = (uint64_t) 0xfacefeedbadc0dedULL
887 		} },
888 		.size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, info),
889 		.str = "info={bpf_fd=-1, info_len=3735928559"
890 		       ", info=0xfacefeedbadc0ded}"
891 	}
892 };
893 
894 
895 static uint32_t prog_load_ids[] = { 0, 1, 0xffffffff, 2718281828, };
896 uint32_t *prog_load_ids_ptr;
897 
898 static void
init_BPF_PROG_QUERY_attr4(struct bpf_attr_check * check)899 init_BPF_PROG_QUERY_attr4(struct bpf_attr_check *check)
900 {
901 	struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data;
902 
903 	if (!prog_load_ids_ptr)
904 		prog_load_ids_ptr = tail_memdup(prog_load_ids,
905 						sizeof(prog_load_ids));
906 
907 	attr->prog_ids = (uintptr_t) prog_load_ids_ptr;
908 	attr->prog_cnt = ARRAY_SIZE(prog_load_ids);
909 }
910 
911 static void
print_BPF_PROG_QUERY_attr4(const struct bpf_attr_check * check,unsigned long addr)912 print_BPF_PROG_QUERY_attr4(const struct bpf_attr_check *check, unsigned long addr)
913 {
914 	printf("query={target_fd=-1153374643"
915 	       ", attach_type=0xfeedface /* BPF_??? */"
916 	       ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
917 	       ", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
918 #if defined(INJECT_RETVAL) && INJECT_RETVAL > 0
919 	       ", prog_ids=[0, 1, 4294967295, 2718281828], prog_cnt=4}"
920 #else
921 	       ", prog_ids=%p, prog_cnt=4}", prog_load_ids_ptr
922 #endif
923 	       );
924 }
925 
926 static void
init_BPF_PROG_QUERY_attr5(struct bpf_attr_check * check)927 init_BPF_PROG_QUERY_attr5(struct bpf_attr_check *check)
928 {
929 	struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data;
930 
931 	if (!prog_load_ids_ptr)
932 		prog_load_ids_ptr = tail_memdup(prog_load_ids,
933 						sizeof(prog_load_ids));
934 
935 	attr->prog_ids = (uintptr_t) prog_load_ids_ptr;
936 	attr->prog_cnt = ARRAY_SIZE(prog_load_ids) + 1;
937 }
938 
939 static void
print_BPF_PROG_QUERY_attr5(const struct bpf_attr_check * check,unsigned long addr)940 print_BPF_PROG_QUERY_attr5(const struct bpf_attr_check *check, unsigned long addr)
941 {
942 	printf("query={target_fd=-1153374643"
943 	       ", attach_type=0xfeedface /* BPF_??? */"
944 	       ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
945 	       ", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
946 #if defined(INJECT_RETVAL) && INJECT_RETVAL > 0
947 	       ", prog_ids=[0, 1, 4294967295, 2718281828, ... /* %p */]"
948 	       ", prog_cnt=5}",
949 	       prog_load_ids_ptr + ARRAY_SIZE(prog_load_ids)
950 #else
951 	       ", prog_ids=%p, prog_cnt=5}", prog_load_ids_ptr
952 #endif
953 	       );
954 }
955 
956 static struct bpf_attr_check BPF_PROG_QUERY_checks[] = {
957 	{
958 		.data = { .BPF_PROG_QUERY_data = { .target_fd = -1 } },
959 		.size = offsetofend(struct BPF_PROG_QUERY_struct, target_fd),
960 		.str = "query={target_fd=-1"
961 		       ", attach_type=BPF_CGROUP_INET_INGRESS, query_flags=0"
962 		       ", attach_flags=0, prog_ids=NULL, prog_cnt=0}",
963 	},
964 	{ /* 1 */
965 		.data = { .BPF_PROG_QUERY_data = {
966 			.target_fd = 3141592653U,
967 			.attach_type = 16,
968 			.query_flags = 1,
969 			.attach_flags = 3,
970 		} },
971 		.size = offsetofend(struct BPF_PROG_QUERY_struct, attach_flags),
972 		.str = "query={target_fd=-1153374643"
973 		       ", attach_type=BPF_LIRC_MODE2"
974 		       ", query_flags=BPF_F_QUERY_EFFECTIVE"
975 		       ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI"
976 		       ", prog_ids=NULL, prog_cnt=0}",
977 	},
978 	{ /* 2 */
979 		.data = { .BPF_PROG_QUERY_data = {
980 			.target_fd = 3141592653U,
981 			.attach_type = 17,
982 			.query_flags = 0xfffffffe,
983 			.attach_flags = 0xfffffffc,
984 			.prog_ids = 0xffffffffffffffffULL,
985 			.prog_cnt = 2718281828,
986 		} },
987 		.size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
988 		.str = "query={target_fd=-1153374643"
989 		       ", attach_type=0x11 /* BPF_??? */"
990 		       ", query_flags=0xfffffffe /* BPF_F_QUERY_??? */"
991 		       ", attach_flags=0xfffffffc /* BPF_F_??? */"
992 		       ", prog_ids="
993 		       BIG_ADDR("0xffffffffffffffff", "0xffffffff")
994 		       ", prog_cnt=2718281828}",
995 	},
996 	{ /* 3 */
997 		.data = { .BPF_PROG_QUERY_data = {
998 			.target_fd = 3141592653U,
999 			.attach_type = 0xfeedface,
1000 			.query_flags = 0xdeadf00d,
1001 			.attach_flags = 0xbeefcafe,
1002 			.prog_ids = 0xffffffffffffffffULL,
1003 			.prog_cnt = 0,
1004 		} },
1005 		.size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1006 		.str = "query={target_fd=-1153374643"
1007 		       ", attach_type=0xfeedface /* BPF_??? */"
1008 		       ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
1009 		       ", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
1010 		       ", prog_ids=" BIG_ADDR_MAYBE("0xffffffffffffffff") "[]"
1011 		       ", prog_cnt=0}",
1012 	},
1013 	{ /* 4 */
1014 		.data = { .BPF_PROG_QUERY_data = {
1015 			.target_fd = 3141592653U,
1016 			.attach_type = 0xfeedface,
1017 			.query_flags = 0xdeadf00d,
1018 			.attach_flags = 0xbeefcafe,
1019 		} },
1020 		.size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1021 		.init_fn = init_BPF_PROG_QUERY_attr4,
1022 		.print_fn = print_BPF_PROG_QUERY_attr4,
1023 	},
1024 	{ /* 5 */
1025 		.data = { .BPF_PROG_QUERY_data = {
1026 			.target_fd = 3141592653U,
1027 			.attach_type = 0xfeedface,
1028 			.query_flags = 0xdeadf00d,
1029 			.attach_flags = 0xbeefcafe,
1030 		} },
1031 		.size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1032 		.init_fn = init_BPF_PROG_QUERY_attr5,
1033 		.print_fn = print_BPF_PROG_QUERY_attr5,
1034 	},
1035 };
1036 
1037 
1038 static void
init_BPF_RAW_TRACEPOINT_attr2(struct bpf_attr_check * check)1039 init_BPF_RAW_TRACEPOINT_attr2(struct bpf_attr_check *check)
1040 {
1041 	/* TODO: test the 128 byte limit */
1042 	static const char tp_name[] = "0123456789qwertyuiop0123456789qwe";
1043 
1044 	struct BPF_RAW_TRACEPOINT_OPEN_struct *attr =
1045 		&check->data.BPF_RAW_TRACEPOINT_OPEN_data;
1046 
1047 	attr->name = (uintptr_t) tp_name;
1048 }
1049 
1050 static struct bpf_attr_check BPF_RAW_TRACEPOINT_OPEN_checks[] = {
1051 	{
1052 		.data = { .BPF_RAW_TRACEPOINT_OPEN_data = { .name = 0 } },
1053 		.size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1054 				    name),
1055 		.str = "raw_tracepoint={name=NULL, prog_fd=0}",
1056 	},
1057 	{ /* 1 */
1058 		.data = { .BPF_RAW_TRACEPOINT_OPEN_data = {
1059 			.name = 0xffffffff00000000ULL,
1060 			.prog_fd = 0xdeadbeef,
1061 		} },
1062 		.size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1063 				    prog_fd),
1064 		.str = "raw_tracepoint="
1065 		       "{name=" BIG_ADDR("0xffffffff00000000", "NULL")
1066 		       ", prog_fd=-559038737}",
1067 	},
1068 	{
1069 		.data = { .BPF_RAW_TRACEPOINT_OPEN_data = {
1070 			.prog_fd = 0xdeadbeef,
1071 		} },
1072 		.size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1073 				    prog_fd),
1074 		.init_fn = init_BPF_RAW_TRACEPOINT_attr2,
1075 		.str = "raw_tracepoint="
1076 		       "{name=\"0123456789qwertyuiop0123456789qw\"..."
1077 		       ", prog_fd=-559038737}",
1078 	}
1079 };
1080 
1081 
1082 #define CHK(cmd_) \
1083 	{ \
1084 		cmd_, #cmd_, \
1085 		cmd_##_checks, ARRAY_SIZE(cmd_##_checks), \
1086 	} \
1087 	/* End of CHK definition */
1088 
1089 int
main(void)1090 main(void)
1091 {
1092 	static const struct bpf_check checks[] = {
1093 		CHK(BPF_MAP_CREATE),
1094 		CHK(BPF_MAP_LOOKUP_ELEM),
1095 		CHK(BPF_MAP_UPDATE_ELEM),
1096 		CHK(BPF_MAP_DELETE_ELEM),
1097 		CHK(BPF_MAP_GET_NEXT_KEY),
1098 		CHK(BPF_PROG_LOAD),
1099 		CHK(BPF_OBJ_PIN),
1100 		CHK(BPF_OBJ_GET),
1101 		CHK(BPF_PROG_ATTACH),
1102 		CHK(BPF_PROG_DETACH),
1103 		CHK(BPF_PROG_TEST_RUN),
1104 		CHK(BPF_PROG_GET_NEXT_ID),
1105 		CHK(BPF_MAP_GET_NEXT_ID),
1106 		CHK(BPF_PROG_GET_FD_BY_ID),
1107 		CHK(BPF_MAP_GET_FD_BY_ID),
1108 		CHK(BPF_OBJ_GET_INFO_BY_FD),
1109 		CHK(BPF_PROG_QUERY),
1110 		CHK(BPF_RAW_TRACEPOINT_OPEN),
1111 	};
1112 
1113 	page_size = get_page_size();
1114 	end_of_page = (unsigned long) tail_alloc(1) + 1;
1115 
1116 	for (size_t i = 0; i < ARRAY_SIZE(checks); i++)
1117 		test_bpf(checks + i);
1118 
1119 	sys_bpf(0xfacefeed, 0, (kernel_ulong_t) 0xfacefeedbadc0dedULL);
1120 	printf("bpf(0xfacefeed /* BPF_??? */, NULL, %u) = %s\n",
1121 	       0xbadc0dedu, errstr);
1122 
1123 	sys_bpf(0xfacefeed, end_of_page, 40);
1124 	printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n",
1125 	       end_of_page, errstr);
1126 
1127 	puts("+++ exited with 0 +++");
1128 	return 0;
1129 }
1130