2 * Check bpf syscall decoding.
4 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
5 * Copyright (c) 2015-2018 The strace developers.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
39 #include <asm/unistd.h>
42 #ifdef HAVE_LINUX_BPF_H
43 # include <linux/bpf.h>
47 #include "print_fields.h"
50 #include "xlat/bpf_commands.h"
52 #ifndef HAVE_STRUCT_BPF_INSN
62 #define BPF_ATTR_DATA_FIELD(cmd_) struct cmd_ ## _struct cmd_ ## _data
65 BPF_ATTR_DATA_FIELD(BPF_MAP_CREATE);
66 BPF_ATTR_DATA_FIELD(BPF_MAP_LOOKUP_ELEM);
67 BPF_ATTR_DATA_FIELD(BPF_MAP_UPDATE_ELEM);
68 BPF_ATTR_DATA_FIELD(BPF_MAP_DELETE_ELEM);
69 BPF_ATTR_DATA_FIELD(BPF_MAP_GET_NEXT_KEY);
70 BPF_ATTR_DATA_FIELD(BPF_PROG_LOAD);
71 BPF_ATTR_DATA_FIELD(BPF_OBJ_PIN);
72 BPF_ATTR_DATA_FIELD(BPF_PROG_ATTACH);
73 BPF_ATTR_DATA_FIELD(BPF_PROG_DETACH);
74 BPF_ATTR_DATA_FIELD(BPF_PROG_TEST_RUN);
75 BPF_ATTR_DATA_FIELD(BPF_PROG_GET_NEXT_ID);
76 BPF_ATTR_DATA_FIELD(BPF_PROG_GET_FD_BY_ID);
77 BPF_ATTR_DATA_FIELD(BPF_MAP_GET_FD_BY_ID);
78 BPF_ATTR_DATA_FIELD(BPF_OBJ_GET_INFO_BY_FD);
79 BPF_ATTR_DATA_FIELD(BPF_PROG_QUERY);
83 struct bpf_attr_check {
84 union bpf_attr_data data;
87 void (*init_fn)(struct bpf_attr_check *check);
88 void (*print_fn)(const struct bpf_attr_check *check,
95 const struct bpf_attr_check *checks;
99 static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL;
100 static const char *errstr;
101 static unsigned int sizeof_attr = sizeof(union bpf_attr_data);
102 static unsigned int page_size;
103 static unsigned long end_of_page;
106 sys_bpf(kernel_ulong_t cmd, kernel_ulong_t attr, kernel_ulong_t size)
108 long rc = syscall(__NR_bpf, cmd, attr, size);
109 errstr = sprintrc(rc);
114 # define print_extra_data(addr_, offs_, size_) \
116 printf("/* bytes %u..%u */ ", (offs_), (size_) + (offs_) - 1); \
117 print_quoted_hex((addr_) + (offs_), (size_)); \
120 # define print_extra_data(addr_, offs_, size_) printf("...")
124 print_bpf_attr(const struct bpf_attr_check *check, unsigned long addr)
127 check->print_fn(check, addr);
129 printf("%s", check->str);
133 test_bpf(const struct bpf_check *cmd_check)
135 const struct bpf_attr_check *check = 0;
136 const union bpf_attr_data *data = 0;
137 unsigned int offset = 0;
140 sys_bpf(cmd_check->cmd, 0, long_bits | sizeof(union bpf_attr_data));
141 printf("bpf(%s, NULL, %u) = %s\n",
142 cmd_check->cmd_str, sizeof_attr, errstr);
145 unsigned long addr = end_of_page - sizeof_attr;
146 sys_bpf(cmd_check->cmd, addr, long_bits);
147 printf("bpf(%s, %#lx, 0) = %s\n",
148 cmd_check->cmd_str, addr, errstr);
150 for (size_t i = 0; i < cmd_check->count; i++) {
151 check = &cmd_check->checks[i];
153 check->init_fn((struct bpf_attr_check *) check);
155 offset = check->size;
157 addr = end_of_page - offset;
158 memcpy((void *) addr, data, offset);
160 /* starting piece of bpf_attr_data */
161 sys_bpf(cmd_check->cmd, addr, offset);
162 printf("bpf(%s, {", cmd_check->cmd_str);
163 print_bpf_attr(check, addr);
164 printf("}, %u) = %s\n", offset, errstr);
166 /* short read of the starting piece */
167 sys_bpf(cmd_check->cmd, addr + 1, offset);
168 printf("bpf(%s, %#lx, %u) = %s\n",
169 cmd_check->cmd_str, addr + 1, offset, errstr);
172 if (offset < sizeof_attr) {
173 /* short read of the whole bpf_attr_data */
174 memcpy((void *) end_of_page - sizeof_attr + 1, data, offset);
175 addr = end_of_page - sizeof_attr + 1;
176 memset((void *) addr + offset, 0, sizeof_attr - offset - 1);
177 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
178 printf("bpf(%s, %#lx, %u) = %s\n",
179 cmd_check->cmd_str, addr, sizeof_attr, errstr);
181 /* the whole bpf_attr_data */
182 memcpy((void *) end_of_page - sizeof_attr, data, offset);
183 addr = end_of_page - sizeof_attr;
184 memset((void *) addr + offset, 0, sizeof_attr - offset);
185 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
186 printf("bpf(%s, {", cmd_check->cmd_str);
187 print_bpf_attr(check, addr);
188 printf("}, %u) = %s\n", sizeof_attr, errstr);
190 /* non-zero bytes after the relevant part */
191 fill_memory_ex((void *) addr + offset,
192 sizeof_attr - offset, '0', 10);
193 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
194 printf("bpf(%s, {", cmd_check->cmd_str);
195 print_bpf_attr(check, addr);
197 print_extra_data((char *) addr, offset,
198 sizeof_attr - offset);
199 printf("}, %u) = %s\n", sizeof_attr, errstr);
202 /* short read of the whole page */
203 memcpy((void *) end_of_page - page_size + 1, data, offset);
204 addr = end_of_page - page_size + 1;
205 memset((void *) addr + offset, 0, page_size - offset - 1);
206 sys_bpf(cmd_check->cmd, addr, page_size);
207 printf("bpf(%s, %#lx, %u) = %s\n",
208 cmd_check->cmd_str, addr, page_size, errstr);
211 memcpy((void *) end_of_page - page_size, data, offset);
212 addr = end_of_page - page_size;
213 memset((void *) addr + offset, 0, page_size - offset);
214 sys_bpf(cmd_check->cmd, addr, page_size);
215 printf("bpf(%s, {", cmd_check->cmd_str);
216 print_bpf_attr(check, addr);
217 printf("}, %u) = %s\n", page_size, errstr);
219 /* non-zero bytes after the whole bpf_attr_data */
220 fill_memory_ex((void *) addr + offset,
221 page_size - offset, '0', 10);
222 sys_bpf(cmd_check->cmd, addr, page_size);
223 printf("bpf(%s, {", cmd_check->cmd_str);
224 print_bpf_attr(check, addr);
226 print_extra_data((char *) addr, offset,
228 printf("}, %u) = %s\n", page_size, errstr);
230 /* more than a page */
231 sys_bpf(cmd_check->cmd, addr, page_size + 1);
232 printf("bpf(%s, %#lx, %u) = %s\n",
233 cmd_check->cmd_str, addr, page_size + 1, errstr);
237 init_BPF_MAP_CREATE_attr7(struct bpf_attr_check *check)
239 struct BPF_MAP_CREATE_struct *attr = &check->data.BPF_MAP_CREATE_data;
240 attr->map_ifindex = ifindex_lo();
243 static struct bpf_attr_check BPF_MAP_CREATE_checks[] = {
245 .data = { .BPF_MAP_CREATE_data = { .map_type = 2 } },
246 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_type),
247 .str = "map_type=BPF_MAP_TYPE_ARRAY, key_size=0, value_size=0"
251 .data = { .BPF_MAP_CREATE_data = {
258 .numa_node = 3141592653,
259 .map_name = "0123456789abcde",
261 .size = offsetof(struct BPF_MAP_CREATE_struct, map_name) + 8,
262 .str = "map_type=BPF_MAP_TYPE_CPUMAP, key_size=4"
263 ", value_size=8, max_entries=256"
264 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NO_COMMON_LRU"
265 "|BPF_F_NUMA_NODE|BPF_F_RDONLY|BPF_F_WRONLY"
266 "|BPF_F_STACK_BUILD_ID"
268 ", numa_node=3141592653"
269 ", map_name=\"0123456\"...",
273 .data = { .BPF_MAP_CREATE_data = {
275 .key_size = 0xface1e55,
276 .value_size = 0xbadc0ded,
277 .max_entries = 0xbeefcafe,
278 .map_flags = 0xffffffc0,
279 .inner_map_fd = 2718281828,
282 .map_ifindex = 3141592653,
284 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
285 .str = "map_type=0x11 /* BPF_MAP_TYPE_??? */"
286 ", key_size=4207812181, value_size=3134983661"
287 ", max_entries=3203386110"
288 ", map_flags=0xffffffc0 /* BPF_F_??? */"
289 ", inner_map_fd=-1576685468"
290 ", map_name=\"\", map_ifindex=3141592653",
294 .data = { .BPF_MAP_CREATE_data = {
295 .map_type = 0xdeadf00d,
296 .key_size = 0xface1e55,
297 .value_size = 0xbadc0ded,
298 .max_entries = 0xbeefcafe,
299 .map_flags = 0xc0dedead,
300 .inner_map_fd = 2718281828,
303 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_flags),
304 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
305 ", key_size=4207812181, value_size=3134983661"
306 ", max_entries=3203386110"
307 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
308 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
312 .data = { .BPF_MAP_CREATE_data = {
313 .map_type = 0xdeadf00d,
314 .key_size = 0xface1e55,
315 .value_size = 0xbadc0ded,
316 .max_entries = 0xbeefcafe,
317 .map_flags = 0xc0dedead,
318 .inner_map_fd = 2718281828,
321 .size = offsetofend(struct BPF_MAP_CREATE_struct, inner_map_fd),
322 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
323 ", key_size=4207812181, value_size=3134983661"
324 ", max_entries=3203386110"
325 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
326 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
328 ", inner_map_fd=-1576685468",
331 .data = { .BPF_MAP_CREATE_data = {
332 .map_type = 0xdeadf00d,
333 .key_size = 0xface1e55,
334 .value_size = 0xbadc0ded,
335 .max_entries = 0xbeefcafe,
336 .map_flags = 0xc0dedead,
337 .inner_map_fd = 2718281828,
340 .size = offsetofend(struct BPF_MAP_CREATE_struct, numa_node),
341 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
342 ", key_size=4207812181, value_size=3134983661"
343 ", max_entries=3203386110"
344 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
345 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
347 ", inner_map_fd=-1576685468"
348 ", numa_node=4294967295 /* NUMA_NO_NODE */",
351 .data = { .BPF_MAP_CREATE_data = {
352 .map_type = 0xdeadf00d,
353 .key_size = 0xface1e55,
354 .value_size = 0xbadc0ded,
355 .max_entries = 0xbeefcafe,
356 .map_flags = 0xc0dedead,
357 .inner_map_fd = 2718281828,
359 .map_name = "fedcba9876543210",
361 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_name),
362 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
363 ", key_size=4207812181, value_size=3134983661"
364 ", max_entries=3203386110"
365 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
366 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
368 ", inner_map_fd=-1576685468"
369 ", numa_node=4294967295 /* NUMA_NO_NODE */"
370 ", map_name=\"fedcba987654321\"...",
373 .data = { .BPF_MAP_CREATE_data = {
374 .map_type = 0xdeadf00d,
375 .key_size = 0xface1e55,
376 .value_size = 0xbadc0ded,
377 .max_entries = 0xbeefcafe,
378 .map_flags = 0xc0dedead,
379 .inner_map_fd = 2718281828,
381 .map_name = "0123456789abcde",
383 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
384 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
385 ", key_size=4207812181, value_size=3134983661"
386 ", max_entries=3203386110"
387 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
388 "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
390 ", inner_map_fd=-1576685468"
391 ", numa_node=4294967295 /* NUMA_NO_NODE */"
392 ", map_name=\"0123456789abcde\""
393 ", map_ifindex=" IFINDEX_LO_STR,
394 .init_fn = init_BPF_MAP_CREATE_attr7,
398 static const struct bpf_attr_check BPF_MAP_LOOKUP_ELEM_checks[] = {
400 .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1 } },
401 .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, map_fd),
402 .str = "map_fd=-1, key=NULL, value=NULL"
405 .data = { .BPF_MAP_LOOKUP_ELEM_data = {
410 .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, value),
411 .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
415 static const struct bpf_attr_check BPF_MAP_UPDATE_ELEM_checks[] = {
417 .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1 } },
418 .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, map_fd),
419 .str = "map_fd=-1, key=NULL, value=NULL, flags=BPF_ANY"
422 .data = { .BPF_MAP_UPDATE_ELEM_data = {
428 .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags),
429 .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
434 static const struct bpf_attr_check BPF_MAP_DELETE_ELEM_checks[] = {
436 .data = { .BPF_MAP_DELETE_ELEM_data = { .map_fd = -1 } },
437 .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, map_fd),
438 .str = "map_fd=-1, key=NULL"
441 .data = { .BPF_MAP_DELETE_ELEM_data = {
445 .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, key),
446 .str = "map_fd=-1, key=0xdeadbeef"
450 static const struct bpf_attr_check BPF_MAP_GET_NEXT_KEY_checks[] = {
452 .data = { .BPF_MAP_GET_NEXT_KEY_data = { .map_fd = -1 } },
453 .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, map_fd),
454 .str = "map_fd=-1, key=NULL, next_key=NULL"
457 .data = { .BPF_MAP_GET_NEXT_KEY_data = {
460 .next_key = 0xbadc0ded
462 .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, next_key),
463 .str = "map_fd=-1, key=0xdeadbeef, next_key=0xbadc0ded"
467 static const struct bpf_insn insns[] = {
470 static const char license[] = "GPL";
471 static char log_buf[4096];
472 static const char pathname[] = "/sys/fs/bpf/foo/bar";
475 init_BPF_PROG_LOAD_attr3(struct bpf_attr_check *check)
477 struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
478 attr->insns = (uintptr_t) insns;
479 attr->license = (uintptr_t) license;
480 attr->log_buf = (uintptr_t) log_buf;
484 print_BPF_PROG_LOAD_attr3(const struct bpf_attr_check *check, unsigned long addr)
486 printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u, insns=%p"
487 ", license=\"%s\", log_level=2718281828, log_size=4096"
488 ", log_buf=%p, kern_version=KERNEL_VERSION(51966, 240, 13)"
489 ", prog_flags=0x2 /* BPF_F_??? */"
490 ", prog_name=\"0123456789abcde\"..., prog_ifindex=3203399405",
491 (unsigned int) ARRAY_SIZE(insns), insns,
496 init_BPF_PROG_LOAD_attr4(struct bpf_attr_check *check)
498 struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
499 attr->insns = (uintptr_t) insns;
500 attr->license = (uintptr_t) license;
501 attr->log_buf = (uintptr_t) log_buf;
502 attr->prog_ifindex = ifindex_lo();
506 print_BPF_PROG_LOAD_attr4(const struct bpf_attr_check *check, unsigned long addr)
508 printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=%p"
509 ", license=\"%s\", log_level=2718281828, log_size=4096"
510 ", log_buf=%p, kern_version=KERNEL_VERSION(51966, 240, 13)"
511 ", prog_flags=BPF_F_STRICT_ALIGNMENT|0x2"
512 ", prog_name=\"0123456789abcde\"..., prog_ifindex=%s",
513 (unsigned int) ARRAY_SIZE(insns), insns,
514 license, log_buf, IFINDEX_LO_STR);
517 static struct bpf_attr_check BPF_PROG_LOAD_checks[] = {
519 .data = { .BPF_PROG_LOAD_data = { .prog_type = 1 } },
520 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_type),
521 .str = "prog_type=BPF_PROG_TYPE_SOCKET_FILTER"
522 ", insn_cnt=0, insns=NULL, license=NULL"
525 .data = { .BPF_PROG_LOAD_data = {
527 .insn_cnt = 0xbadc0ded,
531 .log_size = 3141592653U,
533 .kern_version = 0xcafef00d,
536 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_flags),
537 .str = "prog_type=0x10 /* BPF_PROG_TYPE_??? */"
538 ", insn_cnt=3134983661, insns=NULL, license=NULL"
539 ", log_level=42, log_size=3141592653, log_buf=NULL"
540 ", kern_version=KERNEL_VERSION(51966, 240, 13)"
544 .data = { .BPF_PROG_LOAD_data = {
546 .insn_cnt = 0xbadc0ded,
547 .insns = 0xffffffff00000000,
548 .license = 0xffffffff00000000,
549 .log_level = 2718281828U,
550 .log_size = sizeof(log_buf),
551 .log_buf = 0xffffffff00000000,
552 .kern_version = 0xcafef00d,
554 .prog_name = "fedcba987654321",
556 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name),
557 .str = "prog_type=BPF_PROG_TYPE_CGROUP_DEVICE"
558 ", insn_cnt=3134983661, insns=0xffffffff00000000"
559 #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4
560 ", license=0xffffffff00000000"
561 #elif defined __arm__ || defined __i386__ || defined __mips__ || \
562 defined __powerpc__ || defined __riscv__ || defined __s390__ \
563 || defined __sparc__ || defined __tile__
564 ", license=0xffffffff00000000 or NULL"
568 ", log_level=2718281828, log_size=4096"
569 ", log_buf=0xffffffff00000000"
570 ", kern_version=KERNEL_VERSION(51966, 240, 13)"
571 ", prog_flags=BPF_F_STRICT_ALIGNMENT"
572 ", prog_name=\"fedcba987654321\"",
575 .data = { .BPF_PROG_LOAD_data = {
577 .insn_cnt = ARRAY_SIZE(insns),
578 .log_level = 2718281828U,
579 .log_size = sizeof(log_buf),
580 .kern_version = 0xcafef00d,
582 .prog_name = "0123456789abcdef",
583 .prog_ifindex = 0xbeeffeed,
585 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_ifindex),
586 .init_fn = init_BPF_PROG_LOAD_attr3,
587 .print_fn = print_BPF_PROG_LOAD_attr3
590 .data = { .BPF_PROG_LOAD_data = {
592 .insn_cnt = ARRAY_SIZE(insns),
593 .log_level = 2718281828U,
594 .log_size = sizeof(log_buf),
595 .kern_version = 0xcafef00d,
597 .prog_name = "0123456789abcdef",
599 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_ifindex),
600 .init_fn = init_BPF_PROG_LOAD_attr4,
601 .print_fn = print_BPF_PROG_LOAD_attr4
606 init_BPF_OBJ_PIN_attr(struct bpf_attr_check *check)
608 struct BPF_OBJ_PIN_struct *attr = &check->data.BPF_OBJ_PIN_data;
609 attr->pathname = (uintptr_t) pathname;
612 static struct bpf_attr_check BPF_OBJ_PIN_checks[] = {
614 .data = { .BPF_OBJ_PIN_data = { .pathname = 0 } },
615 .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
616 .str = "pathname=NULL, bpf_fd=0"
619 .data = { .BPF_OBJ_PIN_data = {
620 .pathname = 0xFFFFFFFFFFFFFFFFULL
622 .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
624 #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4
626 #elif defined __arm__ || defined __i386__ || defined __mips__ || \
627 defined __powerpc__ || defined __riscv__ || defined __s390__ \
628 || defined __sparc__ || defined __tile__
629 "0xffffffffffffffff or 0xffffffff"
636 .data = { .BPF_OBJ_PIN_data = { .bpf_fd = -1 } },
637 .size = offsetofend(struct BPF_OBJ_PIN_struct, bpf_fd),
638 .init_fn = init_BPF_OBJ_PIN_attr,
639 .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
642 .data = { .BPF_OBJ_PIN_data = {
646 .size = offsetofend(struct BPF_OBJ_PIN_struct, file_flags),
647 .init_fn = init_BPF_OBJ_PIN_attr,
648 .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
649 ", file_flags=BPF_F_RDONLY|BPF_F_WRONLY"
653 #define BPF_OBJ_GET_checks BPF_OBJ_PIN_checks
655 static const struct bpf_attr_check BPF_PROG_ATTACH_checks[] = {
657 .data = { .BPF_PROG_ATTACH_data = { .target_fd = -1 } },
658 .size = offsetofend(struct BPF_PROG_ATTACH_struct, target_fd),
659 .str = "target_fd=-1, attach_bpf_fd=0"
660 ", attach_type=BPF_CGROUP_INET_INGRESS, attach_flags=0"
663 .data = { .BPF_PROG_ATTACH_data = {
669 .size = offsetofend(struct BPF_PROG_ATTACH_struct, attach_flags),
670 .str = "target_fd=-1, attach_bpf_fd=-2"
671 ", attach_type=BPF_CGROUP_INET_SOCK_CREATE"
672 ", attach_flags=BPF_F_ALLOW_OVERRIDE"
677 static const struct bpf_attr_check BPF_PROG_DETACH_checks[] = {
679 .data = { .BPF_PROG_DETACH_data = { .target_fd = -1 } },
680 .size = offsetofend(struct BPF_PROG_DETACH_struct, target_fd),
681 .str = "target_fd=-1, attach_type=BPF_CGROUP_INET_INGRESS"
684 .data = { .BPF_PROG_DETACH_data = {
688 .size = offsetofend(struct BPF_PROG_DETACH_struct, attach_type),
689 .str = "target_fd=-1, attach_type=BPF_CGROUP_INET_SOCK_CREATE"
693 static const struct bpf_attr_check BPF_PROG_TEST_RUN_checks[] = {
695 .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1 } },
696 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, prog_fd),
697 .str = "test={prog_fd=-1, retval=0, data_size_in=0"
698 ", data_size_out=0, data_in=NULL, data_out=NULL"
699 ", repeat=0, duration=0}"
702 .data = { .BPF_PROG_TEST_RUN_data = {
704 .retval = 0xfac1fed2,
705 .data_size_in = 0xfac3fed4,
706 .data_size_out = 0xfac5fed6,
707 .data_in = (uint64_t) 0xfacef11dbadc2dedULL,
708 .data_out = (uint64_t) 0xfacef33dbadc4dedULL,
709 .repeat = 0xfac7fed8,
710 .duration = 0xfac9feda
712 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, duration),
713 .str = "test={prog_fd=-1, retval=4207017682"
714 ", data_size_in=4207148756, data_size_out=4207279830"
715 ", data_in=0xfacef11dbadc2ded"
716 ", data_out=0xfacef33dbadc4ded"
717 ", repeat=4207410904, duration=4207541978}"
721 static const struct bpf_attr_check BPF_PROG_GET_NEXT_ID_checks[] = {
723 .data = { .BPF_PROG_GET_NEXT_ID_data = {
724 .start_id = 0xdeadbeef
726 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, start_id),
727 .str = "start_id=3735928559, next_id=0"
730 .data = { .BPF_PROG_GET_NEXT_ID_data = {
731 .start_id = 0xdeadbeef
736 "3724541952" /* 0xde000000 */
738 "239" /* 0x000000ef */
743 .data = { .BPF_PROG_GET_NEXT_ID_data = {
744 .start_id = 0xbadc0ded,
745 .next_id = 0xcafef00d
747 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, next_id),
748 .str = "start_id=3134983661, next_id=3405705229"
751 .data = { .BPF_PROG_GET_NEXT_ID_data = {
752 .start_id = 0xbadc0ded,
753 .next_id = 0xcafef00d,
754 .open_flags = 0xffffff27
756 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, open_flags),
757 .str = "start_id=3134983661, next_id=3405705229"
758 ", open_flags=0xffffff27 /* BPF_F_??? */"
762 #define BPF_MAP_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks
764 static const struct bpf_attr_check BPF_PROG_GET_FD_BY_ID_checks[] = {
766 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
767 .prog_id = 0xdeadbeef
769 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, prog_id),
770 .str = "prog_id=3735928559, next_id=0"
773 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
774 .prog_id = 0xbadc0ded,
775 .next_id = 0xcafef00d
777 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, next_id),
778 .str = "prog_id=3134983661, next_id=3405705229"
781 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
782 .prog_id = 0xbadc0ded,
783 .next_id = 0xcafef00d,
784 .open_flags = 0xffffff27
786 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, open_flags),
787 .str = "prog_id=3134983661, next_id=3405705229"
788 ", open_flags=0xffffff27 /* BPF_F_??? */"
792 static const struct bpf_attr_check BPF_MAP_GET_FD_BY_ID_checks[] = {
794 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
797 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, map_id),
798 .str = "map_id=3735928559, next_id=0"
801 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
802 .map_id = 0xbadc0ded,
803 .next_id = 0xcafef00d
805 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, next_id),
806 .str = "map_id=3134983661, next_id=3405705229"
809 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
810 .map_id = 0xbadc0ded,
811 .next_id = 0xcafef00d,
812 .open_flags = 0xffffff27
814 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags),
815 .str = "map_id=3134983661, next_id=3405705229"
816 ", open_flags=0xffffff27 /* BPF_F_??? */"
820 static const struct bpf_attr_check BPF_OBJ_GET_INFO_BY_FD_checks[] = {
822 .data = { .BPF_OBJ_GET_INFO_BY_FD_data = { .bpf_fd = -1 } },
823 .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, bpf_fd),
824 .str = "info={bpf_fd=-1, info_len=0, info=0}"
827 .data = { .BPF_OBJ_GET_INFO_BY_FD_data = {
829 .info_len = 0xdeadbeef,
830 .info = (uint64_t) 0xfacefeedbadc0dedULL
832 .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, info),
833 .str = "info={bpf_fd=-1, info_len=3735928559"
834 ", info=0xfacefeedbadc0ded}"
839 /* TODO: This is a read/write cmd and we do not check exiting path yet */
840 static const struct bpf_attr_check BPF_PROG_QUERY_checks[] = {
842 .data = { .BPF_PROG_QUERY_data = { .target_fd = -1 } },
843 .size = offsetofend(struct BPF_PROG_QUERY_struct, target_fd),
844 .str = "query={target_fd=-1"
845 ", attach_type=BPF_CGROUP_INET_INGRESS, query_flags=0"
846 ", attach_flags=0, prog_ids=NULL, prog_cnt=0}",
849 .data = { .BPF_PROG_QUERY_data = {
850 .target_fd = 3141592653U,
855 .size = offsetofend(struct BPF_PROG_QUERY_struct, attach_flags),
856 .str = "query={target_fd=-1153374643"
857 ", attach_type=BPF_CGROUP_INET6_POST_BIND"
858 ", query_flags=BPF_F_QUERY_EFFECTIVE"
859 ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI"
860 ", prog_ids=NULL, prog_cnt=0}",
863 .data = { .BPF_PROG_QUERY_data = {
864 .target_fd = 3141592653U,
866 .query_flags = 0xfffffffe,
867 .attach_flags = 0xfffffffc,
868 .prog_ids = 0xffffffffffffffffULL,
869 .prog_cnt = 2718281828,
871 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
872 .str = "query={target_fd=-1153374643"
873 ", attach_type=0xe /* BPF_??? */"
874 ", query_flags=0xfffffffe /* BPF_F_QUERY_??? */"
875 ", attach_flags=0xfffffffc /* BPF_F_??? */"
876 ", prog_ids=0xffffffffffffffff, prog_cnt=2718281828}",
879 .data = { .BPF_PROG_QUERY_data = {
880 .target_fd = 3141592653U,
881 .attach_type = 0xfeedface,
882 .query_flags = 0xdeadf00d,
883 .attach_flags = 0xbeefcafe,
884 .prog_ids = 0xffffffffffffffffULL,
887 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
888 .str = "query={target_fd=-1153374643"
889 ", attach_type=0xfeedface /* BPF_??? */"
890 ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
891 ", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
892 ", prog_ids=0xffffffffffffffff, prog_cnt=0}",
900 cmd_##_checks, ARRAY_SIZE(cmd_##_checks), \
902 /* End of CHK definition */
907 static const struct bpf_check checks[] = {
909 CHK(BPF_MAP_LOOKUP_ELEM),
910 CHK(BPF_MAP_UPDATE_ELEM),
911 CHK(BPF_MAP_DELETE_ELEM),
912 CHK(BPF_MAP_GET_NEXT_KEY),
916 CHK(BPF_PROG_ATTACH),
917 CHK(BPF_PROG_DETACH),
918 CHK(BPF_PROG_TEST_RUN),
919 CHK(BPF_PROG_GET_NEXT_ID),
920 CHK(BPF_MAP_GET_NEXT_ID),
921 CHK(BPF_PROG_GET_FD_BY_ID),
922 CHK(BPF_MAP_GET_FD_BY_ID),
923 CHK(BPF_OBJ_GET_INFO_BY_FD),
927 page_size = get_page_size();
928 end_of_page = (unsigned long) tail_alloc(1) + 1;
930 for (size_t i = 0; i < ARRAY_SIZE(checks); i++)
931 test_bpf(checks + i);
933 sys_bpf(0xfacefeed, 0, (kernel_ulong_t) 0xfacefeedbadc0dedULL);
934 printf("bpf(0xfacefeed /* BPF_??? */, NULL, %u) = %s\n",
935 0xbadc0dedu, errstr);
937 sys_bpf(0xfacefeed, end_of_page, 40);
938 printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n",
939 end_of_page, errstr);
941 puts("+++ exited with 0 +++");