1 /*
2 * Check bpf syscall decoding.
3 *
4 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2015-2023 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12
13 #include <stddef.h>
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <string.h>
17 #include <unistd.h>
18
19 #include "scno.h"
20
21 #ifdef HAVE_LINUX_BPF_H
22 # include <linux/bpf.h>
23 #endif
24
25 #include "bpf_attr.h"
26 #include "print_fields.h"
27 #include "xmalloc.h"
28
29 #include "xlat.h"
30 #include "xlat/bpf_attach_type.h"
31 #include "xlat/bpf_commands.h"
32 #include "xlat/bpf_map_types.h"
33 #include "xlat/bpf_prog_types.h"
34 #include "xlat/bpf_test_run_flags.h"
35
36 #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4
37 # define BIG_ADDR(addr64_, addr32_) addr64_
38 # define BIG_ADDR_MAYBE(addr_)
39 #elif defined __arm__ || defined __i386__ || defined __mips__ \
40 || defined __powerpc__ || defined __riscv || defined __s390__ \
41 || defined __sparc__ || defined __tile__
42 # define BIG_ADDR(addr64_, addr32_) addr64_ " or " addr32_
43 # define BIG_ADDR_MAYBE(addr_) addr_ " or "
44 #else
45 # define BIG_ADDR(addr64_, addr32_) addr32_
46 # define BIG_ADDR_MAYBE(addr_)
47 #endif
48
49 #ifndef FD0_PATH
50 # define FD0_PATH ""
51 #endif
52
53 #ifndef HAVE_STRUCT_BPF_INSN
54 struct bpf_insn {
55 uint8_t code;
56 uint8_t dst_reg:4;
57 uint8_t src_reg:4;
58 int16_t off;
59 int32_t imm;
60 };
61 #endif
62
63 #define BPF_ATTR_DATA_FIELD(cmd_) struct cmd_ ## _struct cmd_ ## _data
64
65 union bpf_attr_data {
66 BPF_ATTR_DATA_FIELD(BPF_MAP_CREATE);
67 BPF_ATTR_DATA_FIELD(BPF_MAP_LOOKUP_ELEM);
68 BPF_ATTR_DATA_FIELD(BPF_MAP_UPDATE_ELEM);
69 BPF_ATTR_DATA_FIELD(BPF_MAP_DELETE_ELEM);
70 BPF_ATTR_DATA_FIELD(BPF_MAP_GET_NEXT_KEY);
71 BPF_ATTR_DATA_FIELD(BPF_PROG_LOAD);
72 BPF_ATTR_DATA_FIELD(BPF_OBJ_PIN);
73 BPF_ATTR_DATA_FIELD(BPF_PROG_ATTACH);
74 BPF_ATTR_DATA_FIELD(BPF_PROG_DETACH);
75 BPF_ATTR_DATA_FIELD(BPF_PROG_TEST_RUN);
76 BPF_ATTR_DATA_FIELD(BPF_PROG_GET_NEXT_ID);
77 BPF_ATTR_DATA_FIELD(BPF_PROG_GET_FD_BY_ID);
78 BPF_ATTR_DATA_FIELD(BPF_MAP_GET_FD_BY_ID);
79 BPF_ATTR_DATA_FIELD(BPF_OBJ_GET_INFO_BY_FD);
80 BPF_ATTR_DATA_FIELD(BPF_PROG_QUERY);
81 BPF_ATTR_DATA_FIELD(BPF_RAW_TRACEPOINT_OPEN);
82 BPF_ATTR_DATA_FIELD(BPF_BTF_LOAD);
83 BPF_ATTR_DATA_FIELD(BPF_BTF_GET_FD_BY_ID);
84 BPF_ATTR_DATA_FIELD(BPF_TASK_FD_QUERY);
85 BPF_ATTR_DATA_FIELD(BPF_MAP_FREEZE);
86 BPF_ATTR_DATA_FIELD(BPF_MAP_LOOKUP_BATCH);
87 BPF_ATTR_DATA_FIELD(BPF_MAP_UPDATE_BATCH);
88 BPF_ATTR_DATA_FIELD(BPF_MAP_DELETE_BATCH);
89 BPF_ATTR_DATA_FIELD(BPF_LINK_CREATE);
90 BPF_ATTR_DATA_FIELD(BPF_LINK_UPDATE);
91 BPF_ATTR_DATA_FIELD(BPF_LINK_GET_FD_BY_ID);
92 BPF_ATTR_DATA_FIELD(BPF_ENABLE_STATS);
93 BPF_ATTR_DATA_FIELD(BPF_ITER_CREATE);
94 BPF_ATTR_DATA_FIELD(BPF_LINK_DETACH);
95 BPF_ATTR_DATA_FIELD(BPF_PROG_BIND_MAP);
96 char char_data[256];
97 };
98
99 struct bpf_attr_check {
100 union bpf_attr_data data;
101 size_t size;
102 size_t iters;
103 const char *str;
104 void (*init_fn)(struct bpf_attr_check *check, size_t idx);
105 void (*print_fn)(const struct bpf_attr_check *check,
106 unsigned long addr, size_t idx);
107 };
108
109 struct bpf_check {
110 kernel_ulong_t cmd;
111 const char *cmd_str;
112 const struct bpf_attr_check *checks;
113 size_t count;
114 };
115
116 static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL;
117 static const char *errstr;
118 static const char *at_fdcwd_str;
119 static const unsigned int sizeof_attr = sizeof(union bpf_attr_data);
120 static unsigned int page_size;
121 static unsigned long end_of_page;
122
123 static long
124 sys_bpf(kernel_ulong_t cmd, kernel_ulong_t attr, kernel_ulong_t size)
125 {
126 long rc = syscall(__NR_bpf, cmd, attr, size);
127
128 errstr = sprintrc(rc);
129
130 #ifdef INJECT_RETVAL
131 if (rc != INJECT_RETVAL)
132 error_msg_and_fail("Got a return value of %ld != %ld",
133 rc, (long) INJECT_RETVAL);
134
135 static char inj_errstr[4096];
136
137 snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
138 errstr = inj_errstr;
139 #endif
140
141 return rc;
142 }
143
144 #if VERBOSE
145 # define print_extra_data(addr_, offs_, size_) \
146 do { \
147 printf("extra_data="); \
148 print_quoted_hex((addr_) + (offs_), (size_)); \
149 printf(" /* bytes %u..%u */", (offs_), (size_) + (offs_) - 1); \
150 } while (0)
151 #else
152 # define print_extra_data(addr_, offs_, size_) printf("...")
153 #endif
154
155 static void
156 print_bpf_attr(const struct bpf_attr_check *check, unsigned long addr,
157 size_t idx)
158 {
159 if (check->print_fn)
160 check->print_fn(check, addr, idx);
161 else
162 printf("%s", check->str);
163 }
164
165 static void
166 test_bpf(const struct bpf_check *cmd_check)
167 {
168 const struct bpf_attr_check *check = 0;
169 const union bpf_attr_data *data = 0;
170 unsigned int offset = 0;
171 size_t j = 0;
172
173 /* zero addr */
174 sys_bpf(cmd_check->cmd, 0, long_bits | sizeof(union bpf_attr_data));
175 printf("bpf(%s, NULL, %u) = %s\n",
176 cmd_check->cmd_str, sizeof_attr, errstr);
177
178 /* zero size */
179 unsigned long addr = end_of_page - sizeof_attr;
180 sys_bpf(cmd_check->cmd, addr, long_bits);
181 printf("bpf(%s, %#lx, 0) = %s\n",
182 cmd_check->cmd_str, addr, errstr);
183
184 for (size_t i = 0; i < cmd_check->count; i++) {
185 check = &cmd_check->checks[i];
186 for (j = 0; j < MAX(check->iters, 1); j++) {
187 if (check->init_fn)
188 check->init_fn((struct bpf_attr_check *) check, j);
189 data = &check->data;
190 offset = check->size;
191
192 addr = end_of_page - offset;
193 memcpy((void *) addr, data, offset);
194
195 /* starting piece of bpf_attr_data */
196 sys_bpf(cmd_check->cmd, addr, offset);
197 printf("bpf(%s, {", cmd_check->cmd_str);
198 print_bpf_attr(check, addr, j);
199 printf("}, %u) = %s\n", offset, errstr);
200
201 /* short read of the starting piece */
202 sys_bpf(cmd_check->cmd, addr + 1, offset);
203 printf("bpf(%s, %#lx, %u) = %s\n",
204 cmd_check->cmd_str, addr + 1, offset, errstr);
205 }
206 }
207
208 j = MAX(check->iters, 1) - 1;
209
210 if (offset < sizeof_attr) {
211 /* short read of the whole bpf_attr_data */
212 memcpy((void *) end_of_page - sizeof_attr + 1, data, offset);
213 addr = end_of_page - sizeof_attr + 1;
214 memset((void *) addr + offset, 0, sizeof_attr - offset - 1);
215 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
216 printf("bpf(%s, %#lx, %u) = %s\n",
217 cmd_check->cmd_str, addr, sizeof_attr, errstr);
218
219 /* the whole bpf_attr_data */
220 memcpy((void *) end_of_page - sizeof_attr, data, offset);
221 addr = end_of_page - sizeof_attr;
222 memset((void *) addr + offset, 0, sizeof_attr - offset);
223 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
224 printf("bpf(%s, {", cmd_check->cmd_str);
225 print_bpf_attr(check, addr, j);
226 printf("}, %u) = %s\n", sizeof_attr, errstr);
227
228 /* non-zero bytes after the relevant part */
229 fill_memory_ex((void *) addr + offset,
230 sizeof_attr - offset, '0', 10);
231 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
232 printf("bpf(%s, {", cmd_check->cmd_str);
233 print_bpf_attr(check, addr, j);
234 printf(", ");
235 print_extra_data((char *) addr, offset,
236 sizeof_attr - offset);
237 printf("}, %u) = %s\n", sizeof_attr, errstr);
238 }
239
240 /* short read of the whole page */
241 memcpy((void *) end_of_page - page_size + 1, data, offset);
242 addr = end_of_page - page_size + 1;
243 memset((void *) addr + offset, 0, page_size - offset - 1);
244 sys_bpf(cmd_check->cmd, addr, page_size);
245 printf("bpf(%s, %#lx, %u) = %s\n",
246 cmd_check->cmd_str, addr, page_size, errstr);
247
248 /* the whole page */
249 memcpy((void *) end_of_page - page_size, data, offset);
250 addr = end_of_page - page_size;
251 memset((void *) addr + offset, 0, page_size - offset);
252 sys_bpf(cmd_check->cmd, addr, page_size);
253 printf("bpf(%s, {", cmd_check->cmd_str);
254 print_bpf_attr(check, addr, j);
255 printf("}, %u) = %s\n", page_size, errstr);
256
257 /* non-zero bytes after the whole bpf_attr_data */
258 fill_memory_ex((void *) addr + offset,
259 page_size - offset, '0', 10);
260 sys_bpf(cmd_check->cmd, addr, page_size);
261 printf("bpf(%s, {", cmd_check->cmd_str);
262 print_bpf_attr(check, addr, j);
263 printf(", ");
264 print_extra_data((char *) addr, offset,
265 page_size - offset);
266 printf("}, %u) = %s\n", page_size, errstr);
267
268 /* more than a page */
269 sys_bpf(cmd_check->cmd, addr, page_size + 1);
270 printf("bpf(%s, %#lx, %u) = %s\n",
271 cmd_check->cmd_str, addr, page_size + 1, errstr);
272 }
273
274 static void
275 init_BPF_MAP_CREATE_attr7(struct bpf_attr_check *check, size_t idx)
276 {
277 struct BPF_MAP_CREATE_struct *attr = &check->data.BPF_MAP_CREATE_data;
278 attr->map_ifindex = ifindex_lo();
279 }
280
281 static_assert(ARRAY_SIZE(bpf_map_types_xdata) == 33,
282 "The map_type for tests 1 and 2 below needs to be updated");
283 static struct bpf_attr_check BPF_MAP_CREATE_checks[] = {
284 {
285 .data = { .BPF_MAP_CREATE_data = { .map_type = 2 } },
286 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_type),
287 .str = "map_type=BPF_MAP_TYPE_ARRAY, key_size=0, value_size=0"
288 ", max_entries=0"
289 },
290 { /* 1 */
291 .data = { .BPF_MAP_CREATE_data = {
292 .map_type = 32,
293 .key_size = 4,
294 .value_size = 8,
295 .max_entries = 256,
296 .map_flags = 63,
297 .inner_map_fd = -1,
298 .numa_node = 3141592653,
299 .map_name = "0123456789abcde",
300 } },
301 .size = offsetof(struct BPF_MAP_CREATE_struct, map_name) + 8,
302 .str = "map_type=BPF_MAP_TYPE_CGRP_STORAGE, key_size=4"
303 ", value_size=8, max_entries=256"
304 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NO_COMMON_LRU"
305 "|BPF_F_NUMA_NODE|BPF_F_RDONLY|BPF_F_WRONLY"
306 "|BPF_F_STACK_BUILD_ID"
307 ", inner_map_fd=-1"
308 ", numa_node=3141592653"
309 ", map_name=\"0123456\"...",
310
311 },
312 { /* 2 */
313 .data = { .BPF_MAP_CREATE_data = {
314 .map_type = 33,
315 .key_size = 0xface1e55,
316 .value_size = 0xbadc0ded,
317 .max_entries = 0xbeefcafe,
318 .map_flags = 0xffffc000,
319 .inner_map_fd = 2718281828,
320 .numa_node = -1,
321 .map_name = "",
322 .map_ifindex = 3141592653,
323 } },
324 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
325 .str = "map_type=0x21 /* BPF_MAP_TYPE_??? */"
326 ", key_size=4207812181, value_size=3134983661"
327 ", max_entries=3203386110"
328 ", map_flags=0xffffc000 /* BPF_F_??? */"
329 ", inner_map_fd=-1576685468"
330 ", map_name=\"\", map_ifindex=3141592653",
331
332 },
333 { /* 3 */
334 .data = { .BPF_MAP_CREATE_data = {
335 .map_type = 0xdeadf00d,
336 .key_size = 0xface1e55,
337 .value_size = 0xbadc0ded,
338 .max_entries = 0xbeefcafe,
339 .map_flags = 0xc0defead,
340 .inner_map_fd = 2718281828,
341 .numa_node = -1,
342 } },
343 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_flags),
344 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
345 ", key_size=4207812181, value_size=3134983661"
346 ", max_entries=3203386110"
347 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
348 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
349 "|BPF_F_RDONLY_PROG|BPF_F_CLONE"
350 "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS"
351 "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000",
352 },
353 { /* 4 */
354 .data = { .BPF_MAP_CREATE_data = {
355 .map_type = 0xdeadf00d,
356 .key_size = 0xface1e55,
357 .value_size = 0xbadc0ded,
358 .max_entries = 0xbeefcafe,
359 .map_flags = 0xc0defead,
360 .inner_map_fd = 2718281828,
361 .numa_node = -1,
362 } },
363 .size = offsetofend(struct BPF_MAP_CREATE_struct, inner_map_fd),
364 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
365 ", key_size=4207812181, value_size=3134983661"
366 ", max_entries=3203386110"
367 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
368 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
369 "|BPF_F_RDONLY_PROG|BPF_F_CLONE"
370 "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS"
371 "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000"
372 ", inner_map_fd=-1576685468",
373 },
374 { /* 5 */
375 .data = { .BPF_MAP_CREATE_data = {
376 .map_type = 0xdeadf00d,
377 .key_size = 0xface1e55,
378 .value_size = 0xbadc0ded,
379 .max_entries = 0xbeefcafe,
380 .map_flags = 0xc0defead,
381 .inner_map_fd = 2718281828,
382 .numa_node = -1,
383 } },
384 .size = offsetofend(struct BPF_MAP_CREATE_struct, numa_node),
385 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
386 ", key_size=4207812181, value_size=3134983661"
387 ", max_entries=3203386110"
388 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
389 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
390 "|BPF_F_RDONLY_PROG|BPF_F_CLONE"
391 "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS"
392 "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000"
393 ", inner_map_fd=-1576685468"
394 ", numa_node=4294967295 /* NUMA_NO_NODE */",
395 },
396 { /* 6 */
397 .data = { .BPF_MAP_CREATE_data = {
398 .map_type = 0xdeadf00d,
399 .key_size = 0xface1e55,
400 .value_size = 0xbadc0ded,
401 .max_entries = 0xbeefcafe,
402 .map_flags = 0xc0defead,
403 .inner_map_fd = 2718281828,
404 .numa_node = -1,
405 .map_name = "fedcba9876543210",
406 } },
407 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_name),
408 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
409 ", key_size=4207812181, value_size=3134983661"
410 ", max_entries=3203386110"
411 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
412 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
413 "|BPF_F_RDONLY_PROG|BPF_F_CLONE"
414 "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS"
415 "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000"
416 ", inner_map_fd=-1576685468"
417 ", numa_node=4294967295 /* NUMA_NO_NODE */"
418 ", map_name=\"fedcba987654321\"...",
419 },
420 { /* 7 */
421 .data = { .BPF_MAP_CREATE_data = {
422 .map_type = 0xdeadf00d,
423 .key_size = 0xface1e55,
424 .value_size = 0xbadc0ded,
425 .max_entries = 0xbeefcafe,
426 .map_flags = 0xc0defead,
427 .inner_map_fd = 2718281828,
428 .numa_node = -1,
429 .map_name = "0123456789abcde",
430 } },
431 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
432 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
433 ", key_size=4207812181, value_size=3134983661"
434 ", max_entries=3203386110"
435 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
436 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
437 "|BPF_F_RDONLY_PROG|BPF_F_CLONE"
438 "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS"
439 "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000"
440 ", inner_map_fd=-1576685468"
441 ", numa_node=4294967295 /* NUMA_NO_NODE */"
442 ", map_name=\"0123456789abcde\""
443 ", map_ifindex=" IFINDEX_LO_STR,
444 .init_fn = init_BPF_MAP_CREATE_attr7,
445 },
446 { /* 8 */
447 .data = { .BPF_MAP_CREATE_data = {
448 .btf_fd = 0xbadc0ded,
449 .btf_key_type_id = 0xfacefeed,
450 .btf_value_type_id = 0xcafef00d
451 } },
452 .size = offsetofend(struct BPF_MAP_CREATE_struct,
453 btf_value_type_id),
454 .str = "map_type=BPF_MAP_TYPE_UNSPEC"
455 ", key_size=0"
456 ", value_size=0"
457 ", max_entries=0"
458 ", map_flags=0"
459 ", inner_map_fd=0" FD0_PATH
460 ", map_name=\"\""
461 ", map_ifindex=0"
462 ", btf_fd=-1159983635"
463 ", btf_key_type_id=4207869677"
464 ", btf_value_type_id=3405705229"
465 },
466 { /* 9 */
467 .data = { .BPF_MAP_CREATE_data = {
468 .btf_fd = 0xbadc0ded,
469 .btf_key_type_id = 0xfacefeed,
470 .btf_value_type_id = 0xcafef00d,
471 .btf_vmlinux_value_type_id = 0xdeadc0de,
472 } },
473 .size = offsetofend(struct BPF_MAP_CREATE_struct,
474 btf_vmlinux_value_type_id),
475 .str = "map_type=BPF_MAP_TYPE_UNSPEC"
476 ", key_size=0"
477 ", value_size=0"
478 ", max_entries=0"
479 ", map_flags=0"
480 ", inner_map_fd=0" FD0_PATH
481 ", map_name=\"\""
482 ", map_ifindex=0"
483 ", btf_fd=-1159983635"
484 ", btf_key_type_id=4207869677"
485 ", btf_value_type_id=3405705229"
486 ", btf_vmlinux_value_type_id=3735929054"
487 },
488 { /* 10 */
489 .data = { .BPF_MAP_CREATE_data = {
490 .map_type = BPF_MAP_TYPE_BLOOM_FILTER,
491 .map_extra = 4
492 } },
493 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_extra),
494 .str = "map_type=BPF_MAP_TYPE_BLOOM_FILTER"
495 ", key_size=0"
496 ", value_size=0"
497 ", max_entries=0"
498 ", map_flags=0"
499 ", inner_map_fd=0" FD0_PATH
500 ", map_name=\"\""
501 ", map_ifindex=0"
502 ", btf_fd=0" FD0_PATH
503 ", btf_key_type_id=0"
504 ", btf_value_type_id=0"
505 ", btf_vmlinux_value_type_id=0"
506 ", map_extra=4"
507 },
508 };
509
510 static const struct bpf_attr_check BPF_MAP_LOOKUP_ELEM_checks[] = {
511 {
512 .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1 } },
513 .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, map_fd),
514 .str = "map_fd=-1, key=NULL, value=NULL"
515 },
516 {
517 .data = { .BPF_MAP_LOOKUP_ELEM_data = {
518 .map_fd = -1,
519 .key = 0xdeadbeef,
520 .value = 0xbadc0ded,
521 .flags = 4
522 } },
523 .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, flags),
524 .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
525 ", flags=BPF_F_LOCK"
526 }
527 };
528
529 #define BPF_MAP_LOOKUP_AND_DELETE_ELEM_checks BPF_MAP_LOOKUP_ELEM_checks
530
531 static const struct bpf_attr_check BPF_MAP_UPDATE_ELEM_checks[] = {
532 {
533 .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1 } },
534 .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, map_fd),
535 .str = "map_fd=-1, key=NULL, value=NULL, flags=BPF_ANY"
536 },
537 {
538 .data = { .BPF_MAP_UPDATE_ELEM_data = {
539 .map_fd = -1,
540 .key = 0xdeadbeef,
541 .value = 0xbadc0ded,
542 .flags = 2
543 } },
544 .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags),
545 .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
546 ", flags=BPF_EXIST"
547 }
548 };
549
550 static const struct bpf_attr_check BPF_MAP_DELETE_ELEM_checks[] = {
551 {
552 .data = { .BPF_MAP_DELETE_ELEM_data = { .map_fd = -1 } },
553 .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, map_fd),
554 .str = "map_fd=-1, key=NULL"
555 },
556 {
557 .data = { .BPF_MAP_DELETE_ELEM_data = {
558 .map_fd = -1,
559 .key = 0xdeadbeef
560 } },
561 .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, key),
562 .str = "map_fd=-1, key=0xdeadbeef"
563 }
564 };
565
566 static const struct bpf_attr_check BPF_MAP_GET_NEXT_KEY_checks[] = {
567 {
568 .data = { .BPF_MAP_GET_NEXT_KEY_data = { .map_fd = -1 } },
569 .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, map_fd),
570 .str = "map_fd=-1, key=NULL, next_key=NULL"
571 },
572 {
573 .data = { .BPF_MAP_GET_NEXT_KEY_data = {
574 .map_fd = -1,
575 .key = 0xdeadbeef,
576 .next_key = 0xbadc0ded
577 } },
578 .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, next_key),
579 .str = "map_fd=-1, key=0xdeadbeef, next_key=0xbadc0ded"
580 }
581 };
582
583 static const struct bpf_attr_check BPF_MAP_FREEZE_checks[] = {
584 {
585 .data = { .BPF_MAP_FREEZE_data = { .map_fd = -1 } },
586 .size = offsetofend(struct BPF_MAP_FREEZE_struct, map_fd),
587 .str = "map_fd=-1"
588 }
589 };
590
591 static const struct bpf_insn insns[] = {
592 {
593 .code = 0x95,
594 .dst_reg = 10,
595 .src_reg = 11,
596 .off = 0xdead,
597 .imm = 0xbadc0ded,
598 },
599 };
600 static const char license[] = "GPL";
601 static const char pathname[] = "/sys/fs/bpf/foo/bar";
602
603 static char *log_buf;
604 /*
605 * This has to be a macro, otherwise the compiler complains that
606 * initializer element is not constant.
607 */
608 #define log_buf_size 4096U
609
610 static char *
611 get_log_buf(void)
612 {
613 if (!log_buf)
614 log_buf = tail_alloc(log_buf_size);
615 return log_buf;
616 }
617
618 static char *
619 get_log_buf_tail(void)
620 {
621 return get_log_buf() + log_buf_size;
622 }
623
624 #if VERBOSE
625 # define INSNS_FMT \
626 "[{code=BPF_JMP|BPF_K|BPF_EXIT, dst_reg=BPF_REG_10" \
627 ", src_reg=0xb /* BPF_REG_??? */, off=%d, imm=%#x}]"
628 # define INSNS_ARG insns[0].off, insns[0].imm
629 #else
630 # define INSNS_FMT "%p"
631 # define INSNS_ARG insns
632 #endif
633
634 static void
635 init_BPF_PROG_LOAD_attr3(struct bpf_attr_check *check, size_t idx)
636 {
637 struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
638
639 attr->insns = (uintptr_t) insns;
640 attr->license = (uintptr_t) license;
641 attr->log_buf = (uintptr_t) get_log_buf_tail();
642 }
643
644 static void
645 print_BPF_PROG_LOAD_attr3(const struct bpf_attr_check *check,
646 unsigned long addr, size_t idx)
647 {
648 printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u"
649 ", insns=" INSNS_FMT ", license=\"%s\", log_level=2718281828"
650 ", log_size=%u, log_buf=%p"
651 ", kern_version=KERNEL_VERSION(51966, 240, 13)"
652 ", prog_flags=0x20 /* BPF_F_??? */"
653 ", prog_name=\"0123456789abcde\"..., prog_ifindex=3203399405",
654 (unsigned int) ARRAY_SIZE(insns), INSNS_ARG, license,
655 log_buf_size, get_log_buf_tail());
656 }
657
658 static void
659 init_BPF_PROG_LOAD_attr4(struct bpf_attr_check *check, size_t idx)
660 {
661 struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
662
663 attr->insns = (uintptr_t) insns;
664 attr->license = (uintptr_t) license;
665 attr->log_buf = (uintptr_t) get_log_buf();
666 attr->prog_ifindex = ifindex_lo();
667
668 strncpy(log_buf, "log test", 9);
669 }
670
671 static void
672 print_BPF_PROG_LOAD_attr4(const struct bpf_attr_check *check,
673 unsigned long addr, size_t idx)
674 {
675 printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=" INSNS_FMT
676 ", license=\"%s\", log_level=2718281828, log_size=4"
677 ", log_buf=\"log \"..."
678 ", kern_version=KERNEL_VERSION(51966, 240, 13)"
679 ", prog_flags=BPF_F_STRICT_ALIGNMENT|BPF_F_ANY_ALIGNMENT"
680 "|BPF_F_TEST_RND_HI32|BPF_F_TEST_STATE_FREQ|BPF_F_SLEEPABLE"
681 "|0x20, prog_name=\"0123456789abcde\"..., prog_ifindex=%s"
682 ", expected_attach_type=BPF_CGROUP_INET6_BIND",
683 (unsigned int) ARRAY_SIZE(insns), INSNS_ARG,
684 license, IFINDEX_LO_STR);
685 }
686
687 static_assert(ARRAY_SIZE(bpf_prog_types_xdata) == 33,
688 "The prog_type for tests 1 and 5 below needs to be updated");
689 static struct bpf_attr_check BPF_PROG_LOAD_checks[] = {
690 {
691 .data = { .BPF_PROG_LOAD_data = { .prog_type = 1 } },
692 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_type),
693 .str = "prog_type=BPF_PROG_TYPE_SOCKET_FILTER"
694 ", insn_cnt=0, insns=NULL, license=NULL"
695 },
696 { /* 1 */
697 .data = { .BPF_PROG_LOAD_data = {
698 .prog_type = 33,
699 .insn_cnt = 0xbadc0ded,
700 .insns = 0,
701 .license = 0,
702 .log_level = 42,
703 .log_size = 3141592653U,
704 .log_buf = 0,
705 .kern_version = 0xcafef00d,
706 .prog_flags = 0,
707 } },
708 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_flags),
709 .str = "prog_type=0x21 /* BPF_PROG_TYPE_??? */"
710 ", insn_cnt=3134983661, insns=NULL, license=NULL"
711 ", log_level=42, log_size=3141592653, log_buf=NULL"
712 ", kern_version=KERNEL_VERSION(51966, 240, 13)"
713 ", prog_flags=0",
714 },
715 { /* 2 */
716 .data = { .BPF_PROG_LOAD_data = {
717 .prog_type = 20,
718 .insn_cnt = 0xbadc0ded,
719 .insns = 0xffffffff00000000,
720 .license = 0xffffffff00000000,
721 .log_level = 2718281828U,
722 .log_size = log_buf_size,
723 .log_buf = 0xffffffff00000000,
724 .kern_version = 0xcafef00d,
725 .prog_flags = 1,
726 .prog_name = "fedcba987654321",
727 } },
728 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name),
729 .str = "prog_type=BPF_PROG_TYPE_LIRC_MODE2"
730 ", insn_cnt=3134983661"
731 ", insns=" BIG_ADDR("0xffffffff00000000", "NULL")
732 ", license=" BIG_ADDR("0xffffffff00000000", "NULL")
733 ", log_level=2718281828, log_size=4096"
734 ", log_buf=" BIG_ADDR("0xffffffff00000000", "NULL")
735 ", kern_version=KERNEL_VERSION(51966, 240, 13)"
736 ", prog_flags=BPF_F_STRICT_ALIGNMENT"
737 ", prog_name=\"fedcba987654321\"",
738 },
739 { /* 3 */
740 .data = { .BPF_PROG_LOAD_data = {
741 .prog_type = 1,
742 .insn_cnt = ARRAY_SIZE(insns),
743 .log_level = 2718281828U,
744 .log_size = log_buf_size,
745 .kern_version = 0xcafef00d,
746 .prog_flags = 32,
747 .prog_name = "0123456789abcdef",
748 .prog_ifindex = 0xbeeffeed,
749 } },
750 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_ifindex),
751 .init_fn = init_BPF_PROG_LOAD_attr3,
752 .print_fn = print_BPF_PROG_LOAD_attr3
753 },
754 { /* 4 */
755 .data = { .BPF_PROG_LOAD_data = {
756 .prog_type = 0,
757 .insn_cnt = ARRAY_SIZE(insns),
758 .log_level = 2718281828U,
759 .log_size = 4,
760 .kern_version = 0xcafef00d,
761 .prog_flags = 0x3f,
762 .prog_name = "0123456789abcdef",
763 .expected_attach_type = 9,
764 } },
765 .size = offsetofend(struct BPF_PROG_LOAD_struct,
766 expected_attach_type),
767 .init_fn = init_BPF_PROG_LOAD_attr4,
768 .print_fn = print_BPF_PROG_LOAD_attr4
769 },
770 { /* 5 */
771 .data = { .BPF_PROG_LOAD_data = {
772 .prog_type = 32,
773 .insn_cnt = 0xbadc0ded,
774 .insns = 0xffffffff00000000,
775 .license = 0xffffffff00000000,
776 .log_level = 2718281828U,
777 .log_size = log_buf_size,
778 .log_buf = 0xffffffff00000000,
779 .kern_version = 0xcafef00d,
780 .prog_flags = 1,
781 .prog_name = "fedcba987654321",
782 } },
783 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name),
784 .str = "prog_type=BPF_PROG_TYPE_NETFILTER"
785 ", insn_cnt=3134983661"
786 ", insns=" BIG_ADDR("0xffffffff00000000", "NULL")
787 ", license=" BIG_ADDR("0xffffffff00000000", "NULL")
788 ", log_level=2718281828, log_size=4096"
789 ", log_buf=" BIG_ADDR("0xffffffff00000000", "NULL")
790 ", kern_version=KERNEL_VERSION(51966, 240, 13)"
791 ", prog_flags=BPF_F_STRICT_ALIGNMENT"
792 ", prog_name=\"fedcba987654321\"",
793 },
794 { /* 6 */
795 .data = { .BPF_PROG_LOAD_data = {
796 .prog_flags = 2,
797 .expected_attach_type = 17,
798 .prog_btf_fd = 0xbadc0ded,
799 .func_info_rec_size = 0xdad1bef2,
800 .func_info = 0xfac1fed2fac3fed4,
801 .func_info_cnt = 0xdad3bef4,
802 .line_info_rec_size = 0xdad5bef6,
803 .line_info = 0xfac5fed5fac7fed8,
804 .line_info_cnt = 0xdad7bef8,
805 .attach_btf_id = 0xdad7befa,
806 .attach_prog_fd = 0xbadc0def,
807 .fd_array = 0xfaceb00c,
808 } },
809 .size = offsetofend(struct BPF_PROG_LOAD_struct, fd_array),
810 .str = "prog_type=BPF_PROG_TYPE_UNSPEC"
811 ", insn_cnt=0"
812 ", insns=NULL"
813 ", license=NULL"
814 ", log_level=0"
815 ", log_size=0"
816 ", log_buf=NULL"
817 ", kern_version=KERNEL_VERSION(0, 0, 0)"
818 ", prog_flags=BPF_F_ANY_ALIGNMENT"
819 ", prog_name=\"\""
820 ", prog_ifindex=0"
821 ", expected_attach_type=BPF_FLOW_DISSECTOR"
822 ", prog_btf_fd=-1159983635"
823 ", func_info_rec_size=3671178994"
824 ", func_info=0xfac1fed2fac3fed4"
825 ", func_info_cnt=3671310068"
826 ", line_info_rec_size=3671441142"
827 ", line_info=0xfac5fed5fac7fed8"
828 ", line_info_cnt=3671572216"
829 ", attach_btf_id=3671572218"
830 ", attach_prog_fd=-1159983633"
831 ", fd_array=0xfaceb00c"
832 },
833 };
834
835 static void
836 init_BPF_OBJ_PIN_attr(struct bpf_attr_check *check, size_t idx)
837 {
838 struct BPF_OBJ_PIN_struct *attr = &check->data.BPF_OBJ_PIN_data;
839 attr->pathname = (uintptr_t) pathname;
840 }
841
842 static void
843 init_BPF_OBJ_PIN_str(struct bpf_attr_check *check, size_t idx)
844 {
845 check->str = xasprintf("pathname=NULL, bpf_fd=-1, file_flags=BPF_F_PATH_FD"
846 ", path_fd=%s", at_fdcwd_str);
847 }
848
849 static struct bpf_attr_check BPF_OBJ_PIN_checks[] = {
850 {
851 .data = { .BPF_OBJ_PIN_data = { .pathname = 0 } },
852 .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
853 .str = "pathname=NULL, bpf_fd=0" FD0_PATH
854 },
855 {
856 .data = { .BPF_OBJ_PIN_data = {
857 .pathname = 0xFFFFFFFFFFFFFFFFULL
858 } },
859 .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
860 .str = "pathname=" BIG_ADDR("0xffffffffffffffff", "0xffffffff")
861 ", bpf_fd=0" FD0_PATH,
862 },
863 {
864 .data = { .BPF_OBJ_PIN_data = { .bpf_fd = -1 } },
865 .size = offsetofend(struct BPF_OBJ_PIN_struct, bpf_fd),
866 .init_fn = init_BPF_OBJ_PIN_attr,
867 .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
868 },
869 {
870 .data = { .BPF_OBJ_PIN_data = {
871 .bpf_fd = -1,
872 .file_flags = 0x18
873 } },
874 .size = offsetofend(struct BPF_OBJ_PIN_struct, file_flags),
875 .init_fn = init_BPF_OBJ_PIN_attr,
876 .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
877 ", file_flags=BPF_F_RDONLY|BPF_F_WRONLY"
878 },
879 {
880 .data = { .BPF_OBJ_PIN_data = {
881 .pathname = 0,
882 .bpf_fd = -1,
883 .file_flags = 0x4000,
884 .path_fd = -100
885 } },
886 .size = offsetofend(struct BPF_OBJ_PIN_struct, path_fd),
887 .init_fn = init_BPF_OBJ_PIN_str,
888 }
889 };
890
891 #define BPF_OBJ_GET_checks BPF_OBJ_PIN_checks
892
893 static const struct bpf_attr_check BPF_PROG_ATTACH_checks[] = {
894 {
895 .data = { .BPF_PROG_ATTACH_data = { .target_fd = -1 } },
896 .size = offsetofend(struct BPF_PROG_ATTACH_struct, target_fd),
897 .str = "target_fd=-1, attach_bpf_fd=0" FD0_PATH
898 ", attach_type=BPF_CGROUP_INET_INGRESS, attach_flags=0"
899 },
900 {
901 .data = { .BPF_PROG_ATTACH_data = {
902 .target_fd = -1,
903 .attach_bpf_fd = -2,
904 .attach_type = 2,
905 .attach_flags = 7
906 } },
907 .size = offsetofend(struct BPF_PROG_ATTACH_struct, attach_flags),
908 .str = "target_fd=-1, attach_bpf_fd=-2"
909 ", attach_type=BPF_CGROUP_INET_SOCK_CREATE"
910 ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI"
911 "|BPF_F_REPLACE"
912 },
913 {
914 .data = { .BPF_PROG_ATTACH_data = {
915 .target_fd = -1,
916 .attach_bpf_fd = -2,
917 .attach_type = 2,
918 .attach_flags = 0xf8,
919 .replace_bpf_fd = -3,
920 } },
921 .size = offsetofend(struct BPF_PROG_ATTACH_struct, replace_bpf_fd),
922 .str = "target_fd=-1, attach_bpf_fd=-2"
923 ", attach_type=BPF_CGROUP_INET_SOCK_CREATE"
924 ", attach_flags=0xf8 /* BPF_F_??? */"
925 ", replace_bpf_fd=-3"
926 },
927 };
928
929
930 static const struct bpf_attr_check BPF_PROG_DETACH_checks[] = {
931 {
932 .data = { .BPF_PROG_DETACH_data = { .target_fd = -1 } },
933 .size = offsetofend(struct BPF_PROG_DETACH_struct, target_fd),
934 .str = "target_fd=-1, attach_type=BPF_CGROUP_INET_INGRESS"
935 },
936 {
937 .data = { .BPF_PROG_DETACH_data = {
938 .target_fd = -1,
939 .attach_type = 2
940 } },
941 .size = offsetofend(struct BPF_PROG_DETACH_struct, attach_type),
942 .str = "target_fd=-1, attach_type=BPF_CGROUP_INET_SOCK_CREATE"
943 }
944 };
945
946 static const struct bpf_attr_check BPF_PROG_TEST_RUN_checks[] = {
947 {
948 .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1 } },
949 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, prog_fd),
950 .str = "test={prog_fd=-1, retval=0, data_size_in=0"
951 ", data_size_out=0, data_in=NULL, data_out=NULL"
952 ", repeat=0, duration=0}"
953 },
954 {
955 .data = { .BPF_PROG_TEST_RUN_data = {
956 .prog_fd = -1,
957 .retval = 0xfac1fed2,
958 .data_size_in = 0xfac3fed4,
959 .data_size_out = 0xfac5fed6,
960 .data_in = (uint64_t) 0xfacef11dbadc2dedULL,
961 .data_out = (uint64_t) 0xfacef33dbadc4dedULL,
962 .repeat = 0xfac7fed8,
963 .duration = 0xfac9feda
964 } },
965 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, duration),
966 .str = "test={prog_fd=-1, retval=4207017682"
967 ", data_size_in=4207148756, data_size_out=4207279830"
968 ", data_in=0xfacef11dbadc2ded"
969 ", data_out=0xfacef33dbadc4ded"
970 ", repeat=4207410904, duration=4207541978}"
971 },
972 {
973 .data = { .BPF_PROG_TEST_RUN_data = {
974 .prog_fd = -1,
975 .retval = 0xfac1fed2,
976 .data_size_in = 0xfac3fed4,
977 .data_size_out = 0xfac5fed6,
978 .data_in = (uint64_t) 0xfacef11dbadc2dedULL,
979 .data_out = (uint64_t) 0xfacef33dbadc4dedULL,
980 .repeat = 0xfac7fed8,
981 .duration = 0xfac9feda,
982 .ctx_size_in = 0,
983 .ctx_size_out = 0xfacdfede,
984 .ctx_in = (uint64_t) 0xfacef55dbadc6dedULL,
985 } },
986 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, ctx_in),
987 .str = "test={prog_fd=-1, retval=4207017682"
988 ", data_size_in=4207148756, data_size_out=4207279830"
989 ", data_in=0xfacef11dbadc2ded"
990 ", data_out=0xfacef33dbadc4ded"
991 ", repeat=4207410904"
992 ", duration=4207541978"
993 ", ctx_size_in=0, ctx_size_out=4207804126"
994 ", ctx_in=0xfacef55dbadc6ded, ctx_out=NULL}"
995 },
996 {
997 .data = { .BPF_PROG_TEST_RUN_data = {
998 .prog_fd = -1,
999 .retval = 0xfac1fed2,
1000 .data_size_in = 0xfac3fed4,
1001 .data_size_out = 0xfac5fed6,
1002 .data_in = (uint64_t) 0xfacef11dbadc2dedULL,
1003 .data_out = (uint64_t) 0xfacef33dbadc4dedULL,
1004 .repeat = 0xfac7fed8,
1005 .duration = 0xfac9feda,
1006 .ctx_size_in = 0xfacbfedc,
1007 .ctx_size_out = 0xfacdfede,
1008 .ctx_in = (uint64_t) 0xfacef55dbadc6dedULL,
1009 .ctx_out = (uint64_t) 0xfacef77dbadc8dedULL,
1010 .flags = BPF_F_TEST_RUN_ON_CPU|BPF_F_TEST_XDP_LIVE_FRAMES,
1011 .cpu = 0,
1012 } },
1013 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, cpu),
1014 .str = "test={prog_fd=-1, retval=4207017682"
1015 ", data_size_in=4207148756, data_size_out=4207279830"
1016 ", data_in=0xfacef11dbadc2ded"
1017 ", data_out=0xfacef33dbadc4ded"
1018 ", repeat=4207410904"
1019 ", duration=4207541978"
1020 ", ctx_size_in=4207673052"
1021 ", ctx_size_out=4207804126"
1022 ", ctx_in=0xfacef55dbadc6ded"
1023 ", ctx_out=0xfacef77dbadc8ded"
1024 ", flags=BPF_F_TEST_RUN_ON_CPU|BPF_F_TEST_XDP_LIVE_FRAMES"
1025 ", cpu=0}"
1026 },
1027 {
1028 .data = { .BPF_PROG_TEST_RUN_data = {
1029 .prog_fd = -1,
1030 .retval = 0xfac1fed2,
1031 .data_size_in = 0xfac3fed4,
1032 .data_size_out = 0xfac5fed6,
1033 .data_in = (uint64_t) 0xfacef11dbadc2dedULL,
1034 .data_out = (uint64_t) 0xfacef33dbadc4dedULL,
1035 .repeat = 0xfac7fed8,
1036 .duration = 0xfac9feda,
1037 .ctx_size_in = 0,
1038 .ctx_size_out = 0,
1039 .ctx_in = 0,
1040 .ctx_out = 0,
1041 .flags = 0xfffffffc,
1042 .cpu = 3141592653,
1043 .batch_size = 2718281828,
1044 } },
1045 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, batch_size),
1046 .str = "test={prog_fd=-1, retval=4207017682"
1047 ", data_size_in=4207148756, data_size_out=4207279830"
1048 ", data_in=0xfacef11dbadc2ded"
1049 ", data_out=0xfacef33dbadc4ded"
1050 ", repeat=4207410904"
1051 ", duration=4207541978"
1052 ", ctx_size_in=0, ctx_size_out=0"
1053 ", ctx_in=NULL, ctx_out=NULL"
1054 ", flags=0xfffffffc /* BPF_F_??? */"
1055 ", cpu=3141592653, batch_size=2718281828}"
1056 },
1057 };
1058
1059 static const struct bpf_attr_check BPF_PROG_GET_NEXT_ID_checks[] = {
1060 {
1061 .data = { .BPF_PROG_GET_NEXT_ID_data = {
1062 .start_id = 0xdeadbeef
1063 } },
1064 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, start_id),
1065 .str = "start_id=3735928559, next_id=0"
1066 },
1067 {
1068 .data = { .BPF_PROG_GET_NEXT_ID_data = {
1069 .start_id = 0xdeadbeef
1070 } },
1071 .size = 1,
1072 /* 0xde000000 0x000000ef */
1073 .str = "start_id=" BE_LE("3724541952", "239") ", next_id=0"
1074 },
1075 {
1076 .data = { .BPF_PROG_GET_NEXT_ID_data = {
1077 .start_id = 0xbadc0ded,
1078 .next_id = 0xcafef00d
1079 } },
1080 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, next_id),
1081 .str = "start_id=3134983661, next_id=3405705229"
1082 },
1083 {
1084 .data = { .BPF_PROG_GET_NEXT_ID_data = {
1085 .start_id = 0xbadc0ded,
1086 .next_id = 0xcafef00d,
1087 .open_flags = 0xffffff27
1088 } },
1089 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, open_flags),
1090 .str = "start_id=3134983661, next_id=3405705229"
1091 ", open_flags=0xffffff27 /* BPF_F_??? */"
1092 }
1093 };
1094
1095 #define BPF_MAP_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks
1096 #define BPF_BTF_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks
1097 #define BPF_LINK_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks
1098
1099 static const struct bpf_attr_check BPF_PROG_GET_FD_BY_ID_checks[] = {
1100 {
1101 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
1102 .prog_id = 0xdeadbeef
1103 } },
1104 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, prog_id),
1105 .str = "prog_id=3735928559, next_id=0"
1106 },
1107 {
1108 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
1109 .prog_id = 0xbadc0ded,
1110 .next_id = 0xcafef00d
1111 } },
1112 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, next_id),
1113 .str = "prog_id=3134983661, next_id=3405705229"
1114 },
1115 {
1116 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
1117 .prog_id = 0xbadc0ded,
1118 .next_id = 0xcafef00d,
1119 .open_flags = 0xffffff27
1120 } },
1121 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, open_flags),
1122 .str = "prog_id=3134983661, next_id=3405705229"
1123 ", open_flags=0xffffff27 /* BPF_F_??? */"
1124 }
1125 };
1126
1127 static const struct bpf_attr_check BPF_MAP_GET_FD_BY_ID_checks[] = {
1128 {
1129 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
1130 .map_id = 0xdeadbeef
1131 } },
1132 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, map_id),
1133 .str = "map_id=3735928559, next_id=0"
1134 },
1135 {
1136 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
1137 .map_id = 0xbadc0ded,
1138 .next_id = 0xcafef00d
1139 } },
1140 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, next_id),
1141 .str = "map_id=3134983661, next_id=3405705229"
1142 },
1143 {
1144 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
1145 .map_id = 0xbadc0ded,
1146 .next_id = 0xcafef00d,
1147 .open_flags = 0xffffff27
1148 } },
1149 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags),
1150 .str = "map_id=3134983661, next_id=3405705229"
1151 ", open_flags=0xffffff27 /* BPF_F_??? */"
1152 }
1153 };
1154
1155 static const struct bpf_attr_check BPF_OBJ_GET_INFO_BY_FD_checks[] = {
1156 {
1157 .data = { .BPF_OBJ_GET_INFO_BY_FD_data = { .bpf_fd = -1 } },
1158 .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, bpf_fd),
1159 .str = "info={bpf_fd=-1, info_len=0, info=NULL}"
1160 },
1161 {
1162 .data = { .BPF_OBJ_GET_INFO_BY_FD_data = {
1163 .bpf_fd = -1,
1164 .info_len = 0xdeadbeef,
1165 .info = (uint64_t) 0xfacefeedbadc0dedULL
1166 } },
1167 .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, info),
1168 .str = "info={bpf_fd=-1, info_len=3735928559"
1169 ", info=0xfacefeedbadc0ded}"
1170 }
1171 };
1172
1173
1174 static uint32_t prog_load_ids[] = { 0, 1, 0xffffffff, 2718281828, };
1175 uint32_t *prog_load_ids_ptr;
1176
1177 static void
1178 init_BPF_PROG_QUERY_attr4(struct bpf_attr_check *check, size_t idx)
1179 {
1180 struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data;
1181
1182 if (!prog_load_ids_ptr)
1183 prog_load_ids_ptr = tail_memdup(prog_load_ids,
1184 sizeof(prog_load_ids));
1185
1186 attr->prog_ids = (uintptr_t) prog_load_ids_ptr;
1187 attr->prog_cnt = ARRAY_SIZE(prog_load_ids);
1188 }
1189
1190 static void
1191 print_BPF_PROG_QUERY_attr4(const struct bpf_attr_check *check,
1192 unsigned long addr, size_t idx)
1193 {
1194 printf("query={target_fd=-1153374643"
1195 ", attach_type=0xfeedface /* BPF_??? */"
1196 ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
1197 ", attach_flags=BPF_F_ALLOW_MULTI|BPF_F_REPLACE|0xbeefcaf8"
1198 #if defined(INJECT_RETVAL)
1199 ", prog_ids=[0, 1, 4294967295, 2718281828], prog_cnt=4}"
1200 #else
1201 ", prog_ids=%p, prog_cnt=4}", prog_load_ids_ptr
1202 #endif
1203 );
1204 }
1205
1206 static void
1207 init_BPF_PROG_QUERY_attr5(struct bpf_attr_check *check, size_t idx)
1208 {
1209 struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data;
1210
1211 if (!prog_load_ids_ptr)
1212 prog_load_ids_ptr = tail_memdup(prog_load_ids,
1213 sizeof(prog_load_ids));
1214
1215 attr->prog_ids = (uintptr_t) prog_load_ids_ptr;
1216 attr->prog_cnt = ARRAY_SIZE(prog_load_ids) + 1;
1217 }
1218
1219 static void
1220 print_BPF_PROG_QUERY_attr5(const struct bpf_attr_check *check,
1221 unsigned long addr, size_t idx)
1222 {
1223 printf("query={target_fd=-1153374643"
1224 ", attach_type=0xfeedface /* BPF_??? */"
1225 ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
1226 ", attach_flags=BPF_F_ALLOW_MULTI|BPF_F_REPLACE|0xbeefcaf8"
1227 #if defined(INJECT_RETVAL)
1228 ", prog_ids=[0, 1, 4294967295, 2718281828, ... /* %p */]"
1229 ", prog_cnt=5}",
1230 prog_load_ids_ptr + ARRAY_SIZE(prog_load_ids)
1231 #else
1232 ", prog_ids=%p, prog_cnt=5}", prog_load_ids_ptr
1233 #endif
1234 );
1235 }
1236
1237 static struct bpf_attr_check BPF_PROG_QUERY_checks[] = {
1238 {
1239 .data = { .BPF_PROG_QUERY_data = { .target_fd = -1 } },
1240 .size = offsetofend(struct BPF_PROG_QUERY_struct, target_fd),
1241 .str = "query={target_fd=-1"
1242 ", attach_type=BPF_CGROUP_INET_INGRESS, query_flags=0"
1243 ", attach_flags=0, prog_ids=NULL, prog_cnt=0}",
1244 },
1245 { /* 1 */
1246 .data = { .BPF_PROG_QUERY_data = {
1247 .target_fd = 3141592653U,
1248 .attach_type = 45,
1249 .query_flags = 1,
1250 .attach_flags = 3,
1251 } },
1252 .size = offsetofend(struct BPF_PROG_QUERY_struct, attach_flags),
1253 .str = "query={target_fd=-1153374643"
1254 ", attach_type=BPF_NETFILTER"
1255 ", query_flags=BPF_F_QUERY_EFFECTIVE"
1256 ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI"
1257 ", prog_ids=NULL, prog_cnt=0}",
1258 },
1259 { /* 2 */
1260 .data = { .BPF_PROG_QUERY_data = {
1261 .target_fd = 3141592653U,
1262 .attach_type = 46,
1263 .query_flags = 0xfffffffe,
1264 .attach_flags = 0xfffffff8,
1265 .prog_ids = 0xffffffffffffffffULL,
1266 .prog_cnt = 2718281828,
1267 } },
1268 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1269 .str = "query={target_fd=-1153374643"
1270 ", attach_type=0x2e /* BPF_??? */"
1271 ", query_flags=0xfffffffe /* BPF_F_QUERY_??? */"
1272 ", attach_flags=0xfffffff8 /* BPF_F_??? */"
1273 ", prog_ids="
1274 BIG_ADDR("0xffffffffffffffff", "0xffffffff")
1275 ", prog_cnt=2718281828}",
1276 },
1277 { /* 3 */
1278 .data = { .BPF_PROG_QUERY_data = {
1279 .target_fd = 3141592653U,
1280 .attach_type = 0xfeedface,
1281 .query_flags = 0xdeadf00d,
1282 .attach_flags = 0xbeefcafe,
1283 .prog_ids = 0xffffffffffffffffULL,
1284 .prog_cnt = 0,
1285 } },
1286 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1287 .str = "query={target_fd=-1153374643"
1288 ", attach_type=0xfeedface /* BPF_??? */"
1289 ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
1290 ", attach_flags=BPF_F_ALLOW_MULTI|BPF_F_REPLACE|0xbeefcaf8"
1291 ", prog_ids=" BIG_ADDR_MAYBE("0xffffffffffffffff") "[]"
1292 ", prog_cnt=0}",
1293 },
1294 { /* 4 */
1295 .data = { .BPF_PROG_QUERY_data = {
1296 .target_fd = 3141592653U,
1297 .attach_type = 0xfeedface,
1298 .query_flags = 0xdeadf00d,
1299 .attach_flags = 0xbeefcafe,
1300 } },
1301 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1302 .init_fn = init_BPF_PROG_QUERY_attr4,
1303 .print_fn = print_BPF_PROG_QUERY_attr4,
1304 },
1305 { /* 5 */
1306 .data = { .BPF_PROG_QUERY_data = {
1307 .target_fd = 3141592653U,
1308 .attach_type = 0xfeedface,
1309 .query_flags = 0xdeadf00d,
1310 .attach_flags = 0xbeefcafe,
1311 } },
1312 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1313 .init_fn = init_BPF_PROG_QUERY_attr5,
1314 .print_fn = print_BPF_PROG_QUERY_attr5,
1315 },
1316 };
1317
1318
1319 static void
1320 init_BPF_RAW_TRACEPOINT_attr2(struct bpf_attr_check *check, size_t idx)
1321 {
1322 /* TODO: test the 128 byte limit */
1323 static const char tp_name[] = "0123456789qwertyuiop0123456789qwe";
1324
1325 struct BPF_RAW_TRACEPOINT_OPEN_struct *attr =
1326 &check->data.BPF_RAW_TRACEPOINT_OPEN_data;
1327
1328 attr->name = (uintptr_t) tp_name;
1329 }
1330
1331 static struct bpf_attr_check BPF_RAW_TRACEPOINT_OPEN_checks[] = {
1332 {
1333 .data = { .BPF_RAW_TRACEPOINT_OPEN_data = { .name = 0 } },
1334 .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1335 name),
1336 .str = "raw_tracepoint={name=NULL, prog_fd=0" FD0_PATH "}",
1337 },
1338 { /* 1 */
1339 .data = { .BPF_RAW_TRACEPOINT_OPEN_data = {
1340 .name = 0xffffffff00000000ULL,
1341 .prog_fd = 0xdeadbeef,
1342 } },
1343 .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1344 prog_fd),
1345 .str = "raw_tracepoint="
1346 "{name=" BIG_ADDR("0xffffffff00000000", "NULL")
1347 ", prog_fd=-559038737}",
1348 },
1349 {
1350 .data = { .BPF_RAW_TRACEPOINT_OPEN_data = {
1351 .prog_fd = 0xdeadbeef,
1352 } },
1353 .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1354 prog_fd),
1355 .init_fn = init_BPF_RAW_TRACEPOINT_attr2,
1356 .str = "raw_tracepoint="
1357 "{name=\"0123456789qwertyuiop0123456789qw\"..."
1358 ", prog_fd=-559038737}",
1359 }
1360 };
1361
1362 static void
1363 init_BPF_BTF_LOAD_attr(struct bpf_attr_check *check, size_t idx)
1364 {
1365 static const char sample_btf_data[] = "bPf\0daTum";
1366
1367 static char *btf_data;
1368 if (!btf_data)
1369 btf_data = tail_memdup(sample_btf_data,
1370 sizeof(sample_btf_data) - 1);
1371
1372 struct BPF_BTF_LOAD_struct *attr = &check->data.BPF_BTF_LOAD_data;
1373 attr->btf = (uintptr_t) btf_data;
1374 }
1375
1376 static struct bpf_attr_check BPF_BTF_LOAD_checks[] = {
1377 {
1378 .data = { .BPF_BTF_LOAD_data = { .btf = 0 } },
1379 .size = offsetofend(struct BPF_BTF_LOAD_struct, btf),
1380 .str = "btf=NULL, btf_log_buf=NULL, btf_size=0"
1381 ", btf_log_size=0, btf_log_level=0"
1382 },
1383 { /* 1 */
1384 .data = { .BPF_BTF_LOAD_data = {
1385 .btf_log_buf = 0xfacefeeddeadbeefULL,
1386 .btf_size = 9,
1387 .btf_log_size = -1U,
1388 .btf_log_level = 42
1389 } },
1390 .size = offsetofend(struct BPF_BTF_LOAD_struct, btf_log_level),
1391 .init_fn = init_BPF_BTF_LOAD_attr,
1392 .str = "btf=\"bPf\\0daTum\""
1393 ", btf_log_buf=0xfacefeeddeadbeef"
1394 ", btf_size=9"
1395 ", btf_log_size=4294967295"
1396 ", btf_log_level=42"
1397 }
1398 };
1399
1400 static const struct bpf_attr_check BPF_BTF_GET_FD_BY_ID_checks[] = {
1401 {
1402 .data = { .BPF_BTF_GET_FD_BY_ID_data = { .btf_id = 0xdeadbeef } },
1403 .size = offsetofend(struct BPF_BTF_GET_FD_BY_ID_struct, btf_id),
1404 .str = "btf_id=3735928559"
1405 }
1406 };
1407
1408 static const struct bpf_attr_check BPF_TASK_FD_QUERY_checks[] = {
1409 {
1410 .data = { .BPF_TASK_FD_QUERY_data = { .pid = 1735928559 } },
1411 .size = offsetofend(struct BPF_TASK_FD_QUERY_struct, pid),
1412 .str = "task_fd_query={pid=1735928559, fd=0" FD0_PATH
1413 ", flags=0, buf_len=0, buf=NULL, prog_id=0"
1414 ", fd_type=BPF_FD_TYPE_RAW_TRACEPOINT"
1415 ", probe_offset=0, probe_addr=0}"
1416 },
1417 { /* 1 */
1418 .data = { .BPF_TASK_FD_QUERY_data = {
1419 .pid = 1405705229,
1420 .fd = 0xdeadbeef,
1421 .flags = 0xfacefeed,
1422 .buf_len = 0xdefaced,
1423 .buf = 0xfffffffffffffffe,
1424 .prog_id = 0xbadc0ded,
1425 .fd_type = 5,
1426 .probe_offset = 0xfac1fed2fac3fed4,
1427 .probe_addr = 0xfac5fed5fac7fed8
1428 } },
1429 .size = offsetofend(struct BPF_TASK_FD_QUERY_struct, probe_addr),
1430 .str = "task_fd_query={pid=1405705229"
1431 ", fd=-559038737"
1432 ", flags=4207869677"
1433 ", buf_len=233811181"
1434 ", buf=" BIG_ADDR("0xfffffffffffffffe", "0xfffffffe")
1435 ", prog_id=3134983661"
1436 ", fd_type=BPF_FD_TYPE_URETPROBE"
1437 ", probe_offset=0xfac1fed2fac3fed4"
1438 ", probe_addr=0xfac5fed5fac7fed8}"
1439 }
1440 };
1441
1442 static const struct bpf_attr_check BPF_MAP_LOOKUP_BATCH_checks[] = {
1443 {
1444 .data = { .BPF_MAP_LOOKUP_BATCH_data = { .map_fd = -1 } },
1445 .size = offsetofend(struct BPF_MAP_LOOKUP_BATCH_struct, map_fd ),
1446 .str = "batch={in_batch=NULL, out_batch=NULL, keys=NULL"
1447 ", values=NULL, count=0, map_fd=-1, elem_flags=BPF_ANY"
1448 ", flags=0}"
1449 },
1450 {
1451 .data = { .BPF_MAP_LOOKUP_BATCH_data = {
1452 .in_batch = 0xfacefeed,
1453 .out_batch = 0xbadc0ded,
1454 .keys = 0xdeadf00d,
1455 .values = 0xfffffffe,
1456 .count = 3,
1457 .map_fd = -1,
1458 .elem_flags = 4,
1459 .flags = 4
1460 } },
1461 .size = offsetofend(struct BPF_MAP_LOOKUP_BATCH_struct, flags),
1462 .str = "batch={in_batch=0xfacefeed, out_batch=0xbadc0ded"
1463 ", keys=0xdeadf00d, values=0xfffffffe, count=3"
1464 ", map_fd=-1, elem_flags=BPF_F_LOCK, flags=0x4}"
1465 }
1466 };
1467
1468 static const struct bpf_attr_check BPF_MAP_UPDATE_BATCH_checks[] = {
1469 {
1470 .data = { .BPF_MAP_UPDATE_BATCH_data = { .map_fd = -1 } },
1471 .size = offsetofend(struct BPF_MAP_UPDATE_BATCH_struct, map_fd ),
1472 .str = "batch={keys=NULL, values=NULL, count=0, map_fd=-1"
1473 ", elem_flags=BPF_ANY, flags=0}"
1474 },
1475 {
1476 .data = { .BPF_MAP_UPDATE_BATCH_data = {
1477 .keys = 0xdeadf00d,
1478 .values = 0xfffffffe,
1479 .count = 3,
1480 .map_fd = -1,
1481 .elem_flags = 4,
1482 .flags = 4
1483 } },
1484 .size = offsetofend(struct BPF_MAP_UPDATE_BATCH_struct, flags),
1485 .str = "batch={keys=0xdeadf00d, values=0xfffffffe, count=3"
1486 ", map_fd=-1, elem_flags=BPF_F_LOCK, flags=0x4}"
1487 }
1488 };
1489
1490 static const struct bpf_attr_check BPF_MAP_DELETE_BATCH_checks[] = {
1491 {
1492 .data = { .BPF_MAP_DELETE_BATCH_data = { .map_fd = -1 } },
1493 .size = offsetofend(struct BPF_MAP_DELETE_BATCH_struct, map_fd ),
1494 .str = "batch={keys=NULL, count=0, map_fd=-1"
1495 ", elem_flags=BPF_ANY, flags=0}"
1496 },
1497 {
1498 .data = { .BPF_MAP_DELETE_BATCH_data = {
1499 .keys = 0xdeadf00d,
1500 .count = 3,
1501 .map_fd = -1,
1502 .elem_flags = 4,
1503 .flags = 4
1504 } },
1505 .size = offsetofend(struct BPF_MAP_DELETE_BATCH_struct, flags),
1506 .str = "batch={keys=0xdeadf00d, count=3, map_fd=-1"
1507 ", elem_flags=BPF_F_LOCK, flags=0x4}"
1508 }
1509 };
1510
1511 static void
1512 init_BPF_LINK_CREATE_attr1(struct bpf_attr_check *check, size_t idx)
1513 {
1514 struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data;
1515
1516 attr->attach_type = idx;
1517 }
1518
1519 static void
1520 print_BPF_LINK_CREATE_attr1(const struct bpf_attr_check *check,
1521 unsigned long addr, size_t idx)
1522 {
1523 printf("link_create={prog_fd=-1, target_fd=-559038737"
1524 ", attach_type=%s, flags=0x4}",
1525 sprintxval(bpf_attach_type, idx, "BPF_???"));
1526 }
1527
1528 /* Keep sorted */
1529 static const uint8_t special_attach_types[] =
1530 { 0, BPF_TRACE_ITER, BPF_PERF_EVENT, BPF_TRACE_KPROBE_MULTI };
1531
1532 static void
1533 init_BPF_LINK_CREATE_attr2(struct bpf_attr_check *check, size_t idx)
1534 {
1535 struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data;
1536
1537 /* skip special_attach_types */
1538 for (size_t i = 0; i < ARRAY_SIZE(special_attach_types)
1539 && idx >= special_attach_types[i]; i++, idx++);
1540
1541 attr->attach_type = idx;
1542
1543 check->data.char_data[19] = ' ';
1544 check->data.char_data[23] = 'O';
1545 check->data.char_data[27] = 'H';
1546 check->data.char_data[31] = ' ';
1547 check->data.char_data[35] = 'H';
1548 check->data.char_data[39] = 'A';
1549 check->data.char_data[43] = 'I';
1550 check->data.char_data[47] = '!';
1551 }
1552
1553 static void
1554 print_BPF_LINK_CREATE_attr2(const struct bpf_attr_check *check,
1555 unsigned long addr, size_t idx)
1556 {
1557 /* skip special_attach_types */
1558 for (size_t i = 0; i < ARRAY_SIZE(special_attach_types)
1559 && idx >= special_attach_types[i]; i++, idx++);
1560
1561 printf("link_create={prog_fd=-1, target_fd=-559038737"
1562 ", attach_type=%s, flags=0xbadc0ded}, "
1563 #if VERBOSE
1564 "extra_data=\"\\x00\\x00\\x00\\x20\\x00\\x00\\x00\\x4f"
1565 "\\x00\\x00\\x00\\x48\\x00\\x00\\x00\\x20\\x00\\x00\\x00\\x48"
1566 "\\x00\\x00\\x00\\x41\\x00\\x00\\x00\\x49\\x00\\x00\\x00\\x21\""
1567 " /* bytes 16..47 */"
1568 #else
1569 "..."
1570 #endif
1571 ,
1572 sprintxval(bpf_attach_type, idx, "BPF_???"));
1573 }
1574
1575 static const int iter_info_data[] = { 0, 42, 314159265, 0xbadc0ded, -1 };
1576 static int *iter_info_data_p;
1577
1578 static void
1579 init_BPF_LINK_CREATE_attr7(struct bpf_attr_check *check, size_t idx)
1580 {
1581 struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data;
1582
1583 close(iter_info_data[1]);
1584
1585 if (!iter_info_data_p) {
1586 iter_info_data_p = tail_memdup(iter_info_data,
1587 sizeof(iter_info_data));
1588 }
1589
1590 attr->iter_info = (uintptr_t) iter_info_data_p;
1591 attr->iter_info_len = ARRAY_SIZE(iter_info_data) + idx;
1592 }
1593
1594 static void
1595 print_BPF_LINK_CREATE_attr7(const struct bpf_attr_check *check,
1596 unsigned long addr, size_t idx)
1597 {
1598 printf("link_create={prog_fd=0" FD0_PATH ", target_fd=0" FD0_PATH
1599 ", attach_type=BPF_TRACE_ITER, flags=0"
1600 ", iter_info=[{map={map_fd=0" FD0_PATH "}}, {map={map_fd=42}}"
1601 ", {map={map_fd=314159265}}, {map={map_fd=-1159983635}}"
1602 ", {map={map_fd=-1}}");
1603 if (idx) {
1604 printf(", ... /* %p */",
1605 iter_info_data_p + ARRAY_SIZE(iter_info_data));
1606 }
1607 printf("], iter_info_len=%zu}", ARRAY_SIZE(iter_info_data) + idx);
1608
1609 }
1610
1611 static const char *syms_data[] = { "foo", NULL, "OH\0HAI",
1612 "abcdefghijklmnopqrstuvwxyz0123456789" };
1613 static char **syms_data_p;
1614 static const uint64_t addrs_data[] = { 0, 1, 0xbadc0ded,
1615 0xfacefeeddeadc0deULL };
1616 static uint64_t *addrs_data_p;
1617
1618 static_assert(ARRAY_SIZE(syms_data) == ARRAY_SIZE(addrs_data),
1619 "syms_data and addrs_data have to have the same element count");
1620
1621 static void
1622 init_BPF_LINK_CREATE_attr12(struct bpf_attr_check *check, size_t idx)
1623 {
1624 struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data;
1625
1626 if (!syms_data_p)
1627 syms_data_p = tail_memdup(syms_data, sizeof(syms_data));
1628 if (!addrs_data_p)
1629 addrs_data_p = tail_memdup(addrs_data, sizeof(addrs_data));
1630
1631 attr->kprobe_multi.cnt = ARRAY_SIZE(syms_data) + idx;
1632 attr->kprobe_multi.syms = (uintptr_t) syms_data_p;
1633 attr->kprobe_multi.addrs = (uintptr_t) addrs_data_p;
1634 attr->kprobe_multi.cookies = (uintptr_t) addrs_data_p;
1635 }
1636
1637 static void
1638 print_BPF_LINK_CREATE_attr12(const struct bpf_attr_check *check,
1639 unsigned long addr, size_t idx)
1640 {
1641 printf("link_create={prog_fd=0" FD0_PATH ", target_fd=0" FD0_PATH
1642 ", attach_type=BPF_TRACE_KPROBE_MULTI, flags=0"
1643 ", kprobe_multi={flags=BPF_F_KPROBE_MULTI_RETURN|0xfacebeee"
1644 ", cnt=%zu", ARRAY_SIZE(syms_data) + idx);
1645 printf(", syms=[\"foo\", NULL, \"OH\""
1646 ", \"abcdefghijklmnopqrstuvwxyz012345\"...");
1647 if (idx)
1648 printf(", ... /* %p */", syms_data_p + ARRAY_SIZE(syms_data));
1649 for (size_t i = 0; i < 2; i++) {
1650 printf("], %s=[0, 0x1, 0xbadc0ded, 0xfacefeeddeadc0de",
1651 i ? "cookies" : "addrs");
1652 if (idx) {
1653 printf(", ... /* %p */",
1654 addrs_data_p + ARRAY_SIZE(addrs_data));
1655 }
1656 }
1657 printf("]}}");
1658 }
1659
1660 static struct bpf_attr_check BPF_LINK_CREATE_checks[] = {
1661 { /* 0 */
1662 .data = { .BPF_LINK_CREATE_data = { .prog_fd = 0, .target_fd = 0 } },
1663 .size = offsetofend(struct BPF_LINK_CREATE_struct, target_fd),
1664 .str = "link_create={prog_fd=0" FD0_PATH ", target_fd=0" FD0_PATH
1665 ", attach_type=BPF_CGROUP_INET_INGRESS, flags=0}"
1666 },
1667 { /* 1 */
1668 .data = { .BPF_LINK_CREATE_data = {
1669 .prog_fd = -1,
1670 .target_fd = 0xdeadbeef,
1671 .flags = 4
1672 } },
1673 .size = offsetofend(struct BPF_LINK_CREATE_struct, flags),
1674 .iters = ARRAY_SIZE(bpf_attach_type_xdata),
1675 .init_fn = init_BPF_LINK_CREATE_attr1,
1676 .print_fn = print_BPF_LINK_CREATE_attr1,
1677 },
1678 { /* 2 - all non-special attach_types */
1679 .data = { .BPF_LINK_CREATE_data = {
1680 .prog_fd = -1,
1681 .target_fd = 0xdeadbeef,
1682 .attach_type = 5,
1683 .flags = 0xbadc0ded
1684 } },
1685 .size = 48,
1686 .iters = ARRAY_SIZE(bpf_attach_type_xdata)
1687 - ARRAY_SIZE(special_attach_types),
1688 .init_fn = init_BPF_LINK_CREATE_attr2,
1689 .print_fn = print_BPF_LINK_CREATE_attr2,
1690 },
1691
1692 { /* 3 */
1693 .data = { .BPF_LINK_CREATE_data = {
1694 .attach_type = 0,
1695 } },
1696 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1697 target_btf_id),
1698 .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH
1699 ", attach_type=BPF_CGROUP_INET_INGRESS, flags=0}"
1700 },
1701 { /* 4 */
1702 .data = { .BPF_LINK_CREATE_data = {
1703 .attach_type = 0,
1704 .target_btf_id = 0xfacefeed,
1705 } },
1706 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1707 target_btf_id),
1708 .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH
1709 ", attach_type=BPF_CGROUP_INET_INGRESS, flags=0"
1710 ", target_btf_id=4207869677}"
1711 },
1712
1713 { /* 5 */
1714 .data = { .BPF_LINK_CREATE_data = {
1715 .attach_type = 28,
1716 } },
1717 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1718 iter_info_len),
1719 .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH
1720 ", attach_type=BPF_TRACE_ITER, flags=0"
1721 ", iter_info=NULL, iter_info_len=0}"
1722 },
1723 { /* 6 */
1724 .data = { .BPF_LINK_CREATE_data = {
1725 .attach_type = 28,
1726 .iter_info = 0xffffffff00000000,
1727 .iter_info_len = 0xdeadface,
1728 } },
1729 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1730 iter_info_len),
1731 .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH
1732 ", attach_type=BPF_TRACE_ITER, flags=0"
1733 ", iter_info=" BIG_ADDR("0xffffffff00000000", "NULL")
1734 ", iter_info_len=3735943886}"
1735 },
1736 { /* 7 */
1737 .data = { .BPF_LINK_CREATE_data = {
1738 .attach_type = 28,
1739 } },
1740 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1741 iter_info_len),
1742 .iters = 2,
1743 .init_fn = init_BPF_LINK_CREATE_attr7,
1744 .print_fn = print_BPF_LINK_CREATE_attr7,
1745 },
1746
1747 { /* 8 */
1748 .data = { .BPF_LINK_CREATE_data = {
1749 .attach_type = 41,
1750 } },
1751 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1752 perf_event.bpf_cookie),
1753 .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH
1754 ", attach_type=BPF_PERF_EVENT, flags=0"
1755 ", perf_event={bpf_cookie=0}}"
1756 },
1757 { /* 9 */
1758 .data = { .BPF_LINK_CREATE_data = {
1759 .attach_type = 41,
1760 .perf_event = { .bpf_cookie = 0xdeadc0defacecafeULL },
1761 } },
1762 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1763 perf_event.bpf_cookie),
1764 .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH
1765 ", attach_type=BPF_PERF_EVENT, flags=0"
1766 ", perf_event={bpf_cookie=0xdeadc0defacecafe}}"
1767 },
1768
1769 { /* 10 */
1770 .data = { .BPF_LINK_CREATE_data = {
1771 .attach_type = 42,
1772 } },
1773 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1774 kprobe_multi.cookies),
1775 .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH
1776 ", attach_type=BPF_TRACE_KPROBE_MULTI, flags=0"
1777 ", kprobe_multi={flags=0, cnt=0, syms=NULL, addrs=NULL"
1778 ", cookies=NULL}}"
1779 },
1780 { /* 11 */
1781 .data = { .BPF_LINK_CREATE_data = {
1782 .attach_type = 42,
1783 .kprobe_multi = {
1784 .flags = 0xdeadc0de,
1785 .cnt = 0xbadfaced,
1786 .syms = 0xffffffff00000000,
1787 .addrs = 0xffffffff00000000,
1788 .cookies = 0xffffffff00000000,
1789 },
1790 } },
1791 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1792 kprobe_multi.cookies),
1793 .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH
1794 ", attach_type=BPF_TRACE_KPROBE_MULTI, flags=0"
1795 ", kprobe_multi={flags=0xdeadc0de /* BPF_F_??? */"
1796 ", cnt=3135220973"
1797 ", syms=" BIG_ADDR("0xffffffff00000000", "NULL")
1798 ", addrs=" BIG_ADDR("0xffffffff00000000", "NULL")
1799 ", cookies=" BIG_ADDR("0xffffffff00000000", "NULL") "}}"
1800 },
1801 /*
1802 * Note that here we rely on the fact that this attach_type has the
1803 * largest de-facto attr_size to get the additional checks performed
1804 * with the last check passed.
1805 */
1806 { /* 12 */
1807 .data = { .BPF_LINK_CREATE_data = {
1808 .attach_type = 42,
1809 .kprobe_multi = {
1810 .flags = 0xfacebeef,
1811 }
1812 } },
1813 .size = offsetofend(struct BPF_LINK_CREATE_struct,
1814 kprobe_multi.cookies),
1815 .iters = 2,
1816 .init_fn = init_BPF_LINK_CREATE_attr12,
1817 .print_fn = print_BPF_LINK_CREATE_attr12,
1818 },
1819 };
1820
1821 static const struct bpf_attr_check BPF_LINK_UPDATE_checks[] = {
1822 {
1823 .data = { .BPF_LINK_UPDATE_data = {
1824 .link_fd = -1,
1825 .new_prog_fd = -2
1826 } },
1827 .size = offsetofend(struct BPF_LINK_UPDATE_struct, old_prog_fd),
1828 .str = "link_update={link_fd=-1, new_prog_fd=-2, flags=0}"
1829 },
1830 {
1831 .data = { .BPF_LINK_UPDATE_data = {
1832 .link_fd = -1,
1833 .new_prog_fd = 0xdeadbeef,
1834 .flags = 4,
1835 .old_prog_fd = 0xdeadf00d
1836 } },
1837 .size = offsetofend(struct BPF_LINK_UPDATE_struct, old_prog_fd),
1838 .str = "link_update={link_fd=-1, new_prog_fd=-559038737"
1839 ", flags=BPF_F_REPLACE, old_prog_fd=-559026163}"
1840 }
1841 };
1842
1843 static const struct bpf_attr_check BPF_LINK_GET_FD_BY_ID_checks[] = {
1844 {
1845 .data = { .BPF_LINK_GET_FD_BY_ID_data = { .link_id = 0xdeadbeef } },
1846 .size = offsetofend(struct BPF_LINK_GET_FD_BY_ID_struct, link_id),
1847 .str = "link_id=3735928559"
1848 }
1849 };
1850
1851 static const struct bpf_attr_check BPF_ENABLE_STATS_checks[] = {
1852 {
1853 .data = { .BPF_ENABLE_STATS_data = { .type = 0 } },
1854 .size = offsetofend(struct BPF_ENABLE_STATS_struct, type),
1855 .str = "enable_stats={type=BPF_STATS_RUN_TIME}"
1856 },
1857 {
1858 .data = { .BPF_ENABLE_STATS_data = { .type = 1 } },
1859 .size = offsetofend(struct BPF_ENABLE_STATS_struct, type),
1860 .str = "enable_stats={type=0x1 /* BPF_STATS_??? */}"
1861 }
1862 };
1863
1864 static const struct bpf_attr_check BPF_ITER_CREATE_checks[] = {
1865 {
1866 .data = { .BPF_ITER_CREATE_data = {
1867 .link_fd = -1,
1868 .flags = 0
1869 } },
1870 .size = offsetofend(struct BPF_ITER_CREATE_struct, flags),
1871 .str = "iter_create={link_fd=-1, flags=0}"
1872 },
1873 {
1874 .data = { .BPF_ITER_CREATE_data = {
1875 .link_fd = -1,
1876 .flags = -1U,
1877 } },
1878 .size = offsetofend(struct BPF_ITER_CREATE_struct, flags),
1879 .str = "iter_create={link_fd=-1, flags=0xffffffff}"
1880 }
1881 };
1882
1883 static const struct bpf_attr_check BPF_LINK_DETACH_checks[] = {
1884 {
1885 .data = { .BPF_LINK_DETACH_data = { .link_fd = -1 } },
1886 .size = offsetofend(struct BPF_LINK_DETACH_struct, link_fd),
1887 .str = "link_detach={link_fd=-1}"
1888 }
1889 };
1890
1891 static const struct bpf_attr_check BPF_PROG_BIND_MAP_checks[] = {
1892 {
1893 .data = { .BPF_PROG_BIND_MAP_data = {
1894 .prog_fd = -1,
1895 .map_fd = -2,
1896 .flags = 0
1897 } },
1898 .size = offsetofend(struct BPF_PROG_BIND_MAP_struct, flags),
1899 .str = "prog_bind_map={prog_fd=-1, map_fd=-2, flags=0}"
1900 },
1901 {
1902 .data = { .BPF_PROG_BIND_MAP_data = {
1903 .prog_fd = -1,
1904 .map_fd = -2,
1905 .flags = -1U,
1906 } },
1907 .size = offsetofend(struct BPF_PROG_BIND_MAP_struct, flags),
1908 .str = "prog_bind_map={prog_fd=-1, map_fd=-2, flags=0xffffffff}"
1909 }
1910 };
1911
1912
1913 #define CHK(cmd_) \
1914 { \
1915 cmd_, #cmd_, \
1916 cmd_##_checks, ARRAY_SIZE(cmd_##_checks), \
1917 } \
1918 /* End of CHK definition */
1919
1920 int
1921 main(void)
1922 {
1923 static const struct bpf_check checks[] = {
1924 CHK(BPF_MAP_CREATE),
1925 CHK(BPF_MAP_LOOKUP_ELEM),
1926 CHK(BPF_MAP_UPDATE_ELEM),
1927 CHK(BPF_MAP_DELETE_ELEM),
1928 CHK(BPF_MAP_GET_NEXT_KEY),
1929 CHK(BPF_PROG_LOAD),
1930 CHK(BPF_OBJ_PIN),
1931 CHK(BPF_OBJ_GET),
1932 CHK(BPF_PROG_ATTACH),
1933 CHK(BPF_PROG_DETACH),
1934 CHK(BPF_PROG_TEST_RUN),
1935 CHK(BPF_PROG_GET_NEXT_ID),
1936 CHK(BPF_MAP_GET_NEXT_ID),
1937 CHK(BPF_PROG_GET_FD_BY_ID),
1938 CHK(BPF_MAP_GET_FD_BY_ID),
1939 CHK(BPF_OBJ_GET_INFO_BY_FD),
1940 CHK(BPF_PROG_QUERY),
1941 CHK(BPF_RAW_TRACEPOINT_OPEN),
1942 CHK(BPF_BTF_LOAD),
1943 CHK(BPF_BTF_GET_FD_BY_ID),
1944 CHK(BPF_TASK_FD_QUERY),
1945 CHK(BPF_MAP_LOOKUP_AND_DELETE_ELEM),
1946 CHK(BPF_MAP_FREEZE),
1947 CHK(BPF_BTF_GET_NEXT_ID),
1948 CHK(BPF_MAP_LOOKUP_BATCH),
1949 CHK(BPF_MAP_UPDATE_BATCH),
1950 CHK(BPF_MAP_DELETE_BATCH),
1951 CHK(BPF_LINK_CREATE),
1952 CHK(BPF_LINK_UPDATE),
1953 CHK(BPF_LINK_GET_NEXT_ID),
1954 CHK(BPF_LINK_GET_FD_BY_ID),
1955 CHK(BPF_ENABLE_STATS),
1956 CHK(BPF_ITER_CREATE),
1957 CHK(BPF_LINK_DETACH),
1958 CHK(BPF_PROG_BIND_MAP),
1959 };
1960
1961 page_size = get_page_size();
1962 end_of_page = (unsigned long) tail_alloc(1) + 1;
1963
1964 at_fdcwd_str =
1965 #ifdef YFLAG
1966 xasprintf("AT_FDCWD<%s>", get_fd_path(get_dir_fd(".")));
1967 #else
1968 "AT_FDCWD";
1969 #endif
1970
1971 for (size_t i = 0; i < ARRAY_SIZE(checks); i++)
1972 test_bpf(checks + i);
1973
1974 sys_bpf(0xfacefeed, 0, (kernel_ulong_t) 0xfacefeedbadc0dedULL);
1975 printf("bpf(0xfacefeed /* BPF_??? */, NULL, %u) = %s\n",
1976 0xbadc0dedu, errstr);
1977
1978 sys_bpf(0xfacefeed, end_of_page, 40);
1979 printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n",
1980 end_of_page, errstr);
1981
1982 puts("+++ exited with 0 +++");
1983 return 0;
1984 }