2 * Check bpf syscall decoding.
4 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <asm/unistd.h>
33 #if defined __NR_bpf \
34 && (defined HAVE_UNION_BPF_ATTR_ATTACH_FLAGS \
35 || defined HAVE_UNION_BPF_ATTR_BPF_FD \
36 || defined HAVE_UNION_BPF_ATTR_FLAGS \
37 || defined HAVE_UNION_BPF_ATTR_INFO_INFO \
38 || defined HAVE_UNION_BPF_ATTR_NEXT_ID \
39 || defined HAVE_UNION_BPF_ATTR_NUMA_NODE \
40 || defined HAVE_UNION_BPF_ATTR_PROG_FLAGS \
41 || defined HAVE_UNION_BPF_ATTR_TEST_DURATION)
48 # include <linux/bpf.h>
49 # include "print_fields.h"
51 static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL;
52 static const char *errstr;
53 static unsigned int sizeof_attr = sizeof(union bpf_attr);
54 static unsigned int page_size;
55 static unsigned long end_of_page;
58 sys_bpf(kernel_ulong_t cmd, kernel_ulong_t attr, kernel_ulong_t size)
60 long rc = syscall(__NR_bpf, cmd, attr, size);
61 errstr = sprintrc(rc);
66 # define print_extra_data(addr_, size_) print_quoted_hex((addr_), (size_))
68 # define print_extra_data(addr_, size_) printf("...")
71 # define TEST_BPF_(cmd_, cmd_str_, \
72 init_first_, print_first_, \
73 init_attr_, print_attr_) \
76 sys_bpf(cmd_, 0, long_bits | sizeof(union bpf_attr)); \
77 printf("bpf(%s, NULL, %u) = %s\n", \
78 cmd_str_, sizeof_attr, errstr); \
81 unsigned long addr = end_of_page - sizeof_attr; \
82 sys_bpf(cmd_, addr, long_bits); \
83 printf("bpf(%s, %#lx, 0) = %s\n", \
84 cmd_str_, addr, errstr); \
86 /* the first field only */ \
87 unsigned int offset = init_first_(end_of_page); \
88 addr = end_of_page - offset; \
89 sys_bpf(cmd_, addr, offset); \
90 printf("bpf(%s, {", cmd_str_); \
92 printf("}, %u) = %s\n", offset, errstr); \
94 /* efault after the first field */ \
95 sys_bpf(cmd_, addr, offset + 1); \
96 printf("bpf(%s, %#lx, %u) = %s\n", \
97 cmd_str_, addr, offset + 1, errstr); \
99 /* the relevant part of union bpf_attr */ \
100 offset = init_attr_(end_of_page); \
101 addr = end_of_page - offset; \
102 sys_bpf(cmd_, addr, offset); \
103 printf("bpf(%s, {", cmd_str_); \
105 printf("}, %u) = %s\n", offset, errstr); \
107 /* short read of the relevant part of union bpf_attr */ \
108 sys_bpf(cmd_, addr + 1, offset); \
109 printf("bpf(%s, %#lx, %u) = %s\n", \
110 cmd_str_, addr + 1, offset, errstr); \
112 if (offset < sizeof_attr) { \
113 /* short read of the whole union bpf_attr */ \
114 memmove((void *) end_of_page - sizeof_attr + 1, \
115 (void *) addr, offset); \
116 addr = end_of_page - sizeof_attr + 1; \
117 memset((void *) addr + offset, 0, \
118 sizeof_attr - offset - 1); \
119 sys_bpf(cmd_, addr, sizeof_attr); \
120 printf("bpf(%s, %#lx, %u) = %s\n", \
121 cmd_str_, addr, sizeof_attr, errstr); \
123 /* the whole union bpf_attr */ \
124 memmove((void *) end_of_page - sizeof_attr, \
125 (void *) addr, offset); \
126 addr = end_of_page - sizeof_attr; \
127 memset((void *) addr + offset, 0, \
128 sizeof_attr - offset); \
129 sys_bpf(cmd_, addr, sizeof_attr); \
130 printf("bpf(%s, {", cmd_str_); \
132 printf("}, %u) = %s\n", sizeof_attr, errstr); \
134 /* non-zero bytes after the relevant part */ \
135 fill_memory_ex((void *) addr + offset, \
136 sizeof_attr - offset, '0', 10); \
137 sys_bpf(cmd_, addr, sizeof_attr); \
138 printf("bpf(%s, {", cmd_str_); \
141 print_extra_data((void *) addr + offset, \
142 sizeof_attr - offset); \
143 printf("}, %u) = %s\n", sizeof_attr, errstr); \
146 /* short read of the whole page */ \
147 memmove((void *) end_of_page - page_size + 1, \
148 (void *) addr, offset); \
149 addr = end_of_page - page_size + 1; \
150 memset((void *) addr + offset, 0, \
151 page_size - offset - 1); \
152 sys_bpf(cmd_, addr, page_size); \
153 printf("bpf(%s, %#lx, %u) = %s\n", \
154 cmd_str_, addr, page_size, errstr); \
156 /* the whole page */ \
157 memmove((void *) end_of_page - page_size, \
158 (void *) addr, offset); \
159 addr = end_of_page - page_size; \
160 memset((void *) addr + offset, 0, page_size - offset); \
161 sys_bpf(cmd_, addr, page_size); \
162 printf("bpf(%s, {", cmd_str_); \
164 printf("}, %u) = %s\n", page_size, errstr); \
166 /* non-zero bytes after the whole union bpf_attr */ \
167 fill_memory_ex((void *) addr + offset, \
168 page_size - offset, '0', 10); \
169 sys_bpf(cmd_, addr, page_size); \
170 printf("bpf(%s, {", cmd_str_); \
173 print_extra_data((void *) addr + offset, \
174 page_size - offset); \
175 printf("}, %u) = %s\n", page_size, errstr); \
177 /* more than a page */ \
178 sys_bpf(cmd_, addr, page_size + 1); \
179 printf("bpf(%s, %#lx, %u) = %s\n", \
180 cmd_str_, addr, page_size + 1, errstr); \
182 /* End of TEST_BPF_ definition. */
184 # define TEST_BPF(cmd_) \
185 TEST_BPF_((cmd_), #cmd_, \
186 init_ ## cmd_ ## _first, print_ ## cmd_ ## _first, \
187 init_ ## cmd_ ## _attr, print_ ## cmd_ ## _attr) \
188 /* End of TEST_BPF definition. */
190 # ifdef HAVE_UNION_BPF_ATTR_NUMA_NODE
193 init_BPF_MAP_CREATE_first(const unsigned long eop)
195 static const union bpf_attr attr = { .map_type = 2 };
196 static const unsigned int offset = sizeof(attr.map_type);
197 const unsigned long addr = eop - offset;
199 memcpy((void *) addr, &attr.map_type, offset);
204 print_BPF_MAP_CREATE_first(const unsigned long addr)
206 printf("map_type=BPF_MAP_TYPE_ARRAY, key_size=0, value_size=0"
207 ", max_entries=0, map_flags=0, inner_map_fd=0");
211 init_BPF_MAP_CREATE_attr(const unsigned long eop)
213 static const union bpf_attr attr = {
222 static const unsigned int offset =
223 offsetofend(union bpf_attr, numa_node);
224 const unsigned long addr = eop - offset;
226 memcpy((void *) addr, &attr, offset);
231 print_BPF_MAP_CREATE_attr(const unsigned long addr)
233 printf("map_type=BPF_MAP_TYPE_HASH, key_size=4"
234 ", value_size=8, max_entries=256"
235 ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NO_COMMON_LRU"
236 "|BPF_F_NUMA_NODE, inner_map_fd=-1, numa_node=42");
239 # endif /* HAVE_UNION_BPF_ATTR_NUMA_NODE */
241 # ifdef HAVE_UNION_BPF_ATTR_FLAGS
244 init_BPF_MAP_LOOKUP_ELEM_first(const unsigned long eop)
246 static const union bpf_attr attr = { .map_fd = -1 };
247 static const unsigned int offset = sizeof(attr.map_fd);
248 const unsigned long addr = eop - offset;
250 memcpy((void *) addr, &attr.map_fd, offset);
255 print_BPF_MAP_LOOKUP_ELEM_first(const unsigned long addr)
257 printf("map_fd=-1, key=0, value=0");
261 init_BPF_MAP_LOOKUP_ELEM_attr(const unsigned long eop)
263 static const union bpf_attr attr = {
268 static const unsigned int offset =
269 offsetofend(union bpf_attr, value);
270 const unsigned long addr = eop - offset;
272 memcpy((void *) addr, &attr, offset);
277 print_BPF_MAP_LOOKUP_ELEM_attr(const unsigned long addr)
279 printf("map_fd=-1, key=0xdeadbeef, value=0xbadc0ded");
282 # define init_BPF_MAP_UPDATE_ELEM_first init_BPF_MAP_LOOKUP_ELEM_first
285 print_BPF_MAP_UPDATE_ELEM_first(const unsigned long addr)
287 printf("map_fd=-1, key=0, value=0, flags=BPF_ANY");
291 init_BPF_MAP_UPDATE_ELEM_attr(const unsigned long eop)
293 static const union bpf_attr attr = {
299 static const unsigned int offset =
300 offsetofend(union bpf_attr, flags);
301 const unsigned long addr = eop - offset;
303 memcpy((void *) addr, &attr, offset);
308 print_BPF_MAP_UPDATE_ELEM_attr(const unsigned long addr)
310 printf("map_fd=-1, key=0xdeadbeef, value=0xbadc0ded, flags=BPF_EXIST");
313 # define init_BPF_MAP_DELETE_ELEM_first init_BPF_MAP_LOOKUP_ELEM_first
316 print_BPF_MAP_DELETE_ELEM_first(const unsigned long addr)
318 printf("map_fd=-1, key=0");
322 init_BPF_MAP_DELETE_ELEM_attr(const unsigned long eop)
324 static const union bpf_attr attr = {
328 static const unsigned int offset =
329 offsetofend(union bpf_attr, key);
330 const unsigned long addr = eop - offset;
332 memcpy((void *) addr, &attr, offset);
337 print_BPF_MAP_DELETE_ELEM_attr(const unsigned long addr)
339 printf("map_fd=-1, key=0xdeadbeef");
342 # define init_BPF_MAP_GET_NEXT_KEY_first init_BPF_MAP_LOOKUP_ELEM_first
345 print_BPF_MAP_GET_NEXT_KEY_first(const unsigned long addr)
347 printf("map_fd=-1, key=0, next_key=0");
351 init_BPF_MAP_GET_NEXT_KEY_attr(const unsigned long eop)
353 static const union bpf_attr attr = {
356 .next_key = 0xbadc0ded
358 static const unsigned int offset =
359 offsetofend(union bpf_attr, next_key);
360 const unsigned long addr = eop - offset;
362 memcpy((void *) addr, &attr, offset);
367 print_BPF_MAP_GET_NEXT_KEY_attr(const unsigned long addr)
369 printf("map_fd=-1, key=0xdeadbeef, next_key=0xbadc0ded");
372 # endif /* HAVE_UNION_BPF_ATTR_FLAGS */
374 # ifdef HAVE_UNION_BPF_ATTR_PROG_FLAGS
377 init_BPF_PROG_LOAD_first(const unsigned long eop)
379 static const union bpf_attr attr = { .prog_type = 1 };
380 static const unsigned int offset = sizeof(attr.prog_type);
381 const unsigned long addr = eop - offset;
383 memcpy((void *) addr, &attr.prog_type, offset);
388 print_BPF_PROG_LOAD_first(const unsigned long addr)
391 printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=0, insns=0"
392 ", license=NULL, log_level=0, log_size=0, log_buf=0"
393 ", kern_version=0, prog_flags=0");
396 static const struct bpf_insn insns[] = {
397 { .code = BPF_JMP | BPF_EXIT }
399 static char log_buf[4096];
402 init_BPF_PROG_LOAD_attr(const unsigned long eop)
404 const union bpf_attr attr = {
406 .insn_cnt = ARRAY_SIZE(insns),
407 .insns = (uintptr_t) insns,
408 .license = (uintptr_t) "GPL",
410 .log_size = sizeof(log_buf),
411 .log_buf = (uintptr_t) log_buf,
412 .kern_version = 0xcafef00d,
415 static const unsigned int offset =
416 offsetofend(union bpf_attr, prog_flags);
417 const unsigned long addr = eop - offset;
419 memcpy((void *) addr, &attr, offset);
424 print_BPF_PROG_LOAD_attr(const unsigned long addr)
426 printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u, insns=%p"
427 ", license=\"GPL\", log_level=42, log_size=4096, log_buf=%p"
428 ", kern_version=%u, prog_flags=BPF_F_STRICT_ALIGNMENT",
429 (unsigned int) ARRAY_SIZE(insns), insns,
430 log_buf, 0xcafef00d);
433 # endif /* HAVE_UNION_BPF_ATTR_PROG_FLAGS */
436 * bpf() syscall and its first six commands were introduced in Linux kernel
437 * 3.18. Some additional commands were added afterwards, so we need to take
438 * precautions to make sure the tests compile.
440 * BPF_OBJ_PIN and BPF_OBJ_GET commands appear in kernel 4.4.
442 # ifdef HAVE_UNION_BPF_ATTR_BPF_FD
445 init_BPF_OBJ_PIN_first(const unsigned long eop)
447 static const union bpf_attr attr = {};
448 static const unsigned int offset = sizeof(attr.pathname);
449 const unsigned long addr = eop - offset;
451 memcpy((void *) addr, &attr.pathname, offset);
456 print_BPF_OBJ_PIN_first(const unsigned long addr)
459 printf("pathname=NULL, bpf_fd=0");
463 init_BPF_OBJ_PIN_attr(const unsigned long eop)
465 const union bpf_attr attr = {
466 .pathname = (uintptr_t) "/sys/fs/bpf/foo/bar",
469 static const unsigned int offset =
470 offsetofend(union bpf_attr, bpf_fd);
471 const unsigned long addr = eop - offset;
473 memcpy((void *) addr, &attr, offset);
478 print_BPF_OBJ_PIN_attr(const unsigned long addr)
480 printf("pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1");
483 # define init_BPF_OBJ_GET_first init_BPF_OBJ_PIN_first
484 # define print_BPF_OBJ_GET_first print_BPF_OBJ_PIN_first
485 # define init_BPF_OBJ_GET_attr init_BPF_OBJ_PIN_attr
486 # define print_BPF_OBJ_GET_attr print_BPF_OBJ_PIN_attr
488 # endif /* HAVE_UNION_BPF_ATTR_BPF_FD */
490 /* BPF_PROG_ATTACH and BPF_PROG_DETACH commands appear in kernel 4.10. */
491 # ifdef HAVE_UNION_BPF_ATTR_ATTACH_FLAGS
494 init_BPF_PROG_ATTACH_first(const unsigned long eop)
496 static const union bpf_attr attr = { .target_fd = -1 };
497 static const unsigned int offset = sizeof(attr.target_fd);
498 const unsigned long addr = eop - offset;
500 memcpy((void *) addr, &attr.target_fd, offset);
505 print_BPF_PROG_ATTACH_first(const unsigned long addr)
507 printf("target_fd=-1, attach_bpf_fd=0"
508 ", attach_type=BPF_CGROUP_INET_INGRESS, attach_flags=0");
512 init_BPF_PROG_ATTACH_attr(const unsigned long eop)
514 static const union bpf_attr attr = {
520 static const unsigned int offset =
521 offsetofend(union bpf_attr, attach_flags);
522 const unsigned long addr = eop - offset;
524 memcpy((void *) addr, &attr, offset);
529 print_BPF_PROG_ATTACH_attr(const unsigned long addr)
531 printf("target_fd=-1, attach_bpf_fd=-2"
532 ", attach_type=BPF_CGROUP_INET_SOCK_CREATE"
533 ", attach_flags=BPF_F_ALLOW_OVERRIDE");
536 # define init_BPF_PROG_DETACH_first init_BPF_PROG_ATTACH_first
539 init_BPF_PROG_DETACH_attr(const unsigned long eop)
541 static const union bpf_attr attr = {
545 static const unsigned int offset =
546 offsetofend(union bpf_attr, attach_type);
547 const unsigned long addr = eop - offset;
549 memcpy((void *) addr, &attr, offset);
555 print_BPF_PROG_DETACH_first(const unsigned long addr)
557 printf("target_fd=-1, attach_type=BPF_CGROUP_INET_INGRESS");
561 print_BPF_PROG_DETACH_attr(const unsigned long addr)
563 printf("target_fd=-1, attach_type=BPF_CGROUP_INET_SOCK_CREATE");
566 # endif /* HAVE_UNION_BPF_ATTR_ATTACH_FLAGS */
568 /* BPF_PROG_TEST_RUN command appears in kernel 4.12. */
569 # ifdef HAVE_UNION_BPF_ATTR_TEST_DURATION
572 init_BPF_PROG_TEST_RUN_first(const unsigned long eop)
574 static const union bpf_attr attr = { .test.prog_fd = -1 };
575 static const unsigned int offset = sizeof(attr.test.prog_fd);
576 const unsigned long addr = eop - offset;
578 memcpy((void *) addr, &attr.test.prog_fd, offset);
583 print_BPF_PROG_TEST_RUN_first(const unsigned long addr)
585 printf("test={prog_fd=-1, retval=0, data_size_in=0, data_size_out=0"
586 ", data_in=0, data_out=0, repeat=0, duration=0}");
589 static const union bpf_attr sample_BPF_PROG_TEST_RUN_attr = {
592 .retval = 0xfac1fed2,
593 .data_size_in = 0xfac3fed4,
594 .data_size_out = 0xfac5fed6,
595 .data_in = (uint64_t) 0xfacef11dbadc2ded,
596 .data_out = (uint64_t) 0xfacef33dbadc4ded,
597 .repeat = 0xfac7fed8,
598 .duration = 0xfac9feda
602 init_BPF_PROG_TEST_RUN_attr(const unsigned long eop)
604 static const unsigned int offset =
605 offsetofend(union bpf_attr, test);
606 const unsigned long addr = eop - offset;
608 memcpy((void *) addr, &sample_BPF_PROG_TEST_RUN_attr, offset);
613 print_BPF_PROG_TEST_RUN_attr(const unsigned long addr)
615 PRINT_FIELD_D("test={", sample_BPF_PROG_TEST_RUN_attr.test, prog_fd);
616 PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, retval);
617 PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, data_size_in);
618 PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, data_size_out);
619 PRINT_FIELD_X(", ", sample_BPF_PROG_TEST_RUN_attr.test, data_in);
620 PRINT_FIELD_X(", ", sample_BPF_PROG_TEST_RUN_attr.test, data_out);
621 PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, repeat);
622 PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, duration);
626 # endif /* HAVE_UNION_BPF_ATTR_TEST_DURATION */
628 # ifdef HAVE_UNION_BPF_ATTR_NEXT_ID
631 init_BPF_PROG_GET_NEXT_ID_first(const unsigned long eop)
633 static const union bpf_attr attr = { .start_id = 0xdeadbeef };
634 static const unsigned int offset = sizeof(attr.start_id);
635 const unsigned long addr = eop - offset;
637 memcpy((void *) addr, &attr.start_id, offset);
642 print_BPF_PROG_GET_NEXT_ID_first(const unsigned long addr)
644 printf("start_id=%u, next_id=0", 0xdeadbeef);
648 init_BPF_PROG_GET_NEXT_ID_attr(const unsigned long eop)
650 static const union bpf_attr attr = {
651 .start_id = 0xbadc0ded,
652 .next_id = 0xcafef00d
654 static const unsigned int offset =
655 offsetofend(union bpf_attr, next_id);
656 const unsigned long addr = eop - offset;
658 memcpy((void *) addr, &attr, offset);
663 print_BPF_PROG_GET_NEXT_ID_attr(const unsigned long addr)
665 printf("start_id=%u, next_id=%u", 0xbadc0ded, 0xcafef00d);
668 # define init_BPF_MAP_GET_NEXT_ID_first init_BPF_PROG_GET_NEXT_ID_first
669 # define print_BPF_MAP_GET_NEXT_ID_first print_BPF_PROG_GET_NEXT_ID_first
670 # define init_BPF_MAP_GET_NEXT_ID_attr init_BPF_PROG_GET_NEXT_ID_attr
671 # define print_BPF_MAP_GET_NEXT_ID_attr print_BPF_PROG_GET_NEXT_ID_attr
673 # define init_BPF_PROG_GET_FD_BY_ID_first init_BPF_PROG_GET_NEXT_ID_first
674 # define init_BPF_PROG_GET_FD_BY_ID_attr init_BPF_PROG_GET_NEXT_ID_attr
677 print_BPF_PROG_GET_FD_BY_ID_first(const unsigned long addr)
679 printf("prog_id=%u, next_id=0", 0xdeadbeef);
683 print_BPF_PROG_GET_FD_BY_ID_attr(const unsigned long addr)
685 printf("prog_id=%u, next_id=%u", 0xbadc0ded, 0xcafef00d);
688 # define init_BPF_MAP_GET_FD_BY_ID_first init_BPF_PROG_GET_NEXT_ID_first
689 # define init_BPF_MAP_GET_FD_BY_ID_attr init_BPF_PROG_GET_NEXT_ID_attr
692 print_BPF_MAP_GET_FD_BY_ID_first(const unsigned long addr)
694 printf("map_id=%u, next_id=0", 0xdeadbeef);
698 print_BPF_MAP_GET_FD_BY_ID_attr(const unsigned long addr)
700 printf("map_id=%u, next_id=%u", 0xbadc0ded, 0xcafef00d);
703 # endif /* HAVE_UNION_BPF_ATTR_NEXT_ID */
705 # ifdef HAVE_UNION_BPF_ATTR_INFO_INFO
708 init_BPF_OBJ_GET_INFO_BY_FD_first(const unsigned long eop)
710 static const union bpf_attr attr = { .info.bpf_fd = -1 };
711 static const unsigned int offset = sizeof(attr.info.bpf_fd);
712 const unsigned long addr = eop - offset;
714 memcpy((void *) addr, &attr.info.bpf_fd, offset);
719 print_BPF_OBJ_GET_INFO_BY_FD_first(const unsigned long addr)
721 printf("info={bpf_fd=-1, info_len=0, info=0}");
724 static const union bpf_attr sample_BPF_OBJ_GET_INFO_BY_FD_attr = {
727 .info_len = 0xdeadbeef,
728 .info = (uint64_t) 0xfacefeedbadc0ded
732 init_BPF_OBJ_GET_INFO_BY_FD_attr(const unsigned long eop)
734 static const unsigned int offset =
735 offsetofend(union bpf_attr, info);
736 const unsigned long addr = eop - offset;
738 memcpy((void *) addr, &sample_BPF_OBJ_GET_INFO_BY_FD_attr, offset);
743 print_BPF_OBJ_GET_INFO_BY_FD_attr(const unsigned long addr)
745 PRINT_FIELD_D("info={", sample_BPF_OBJ_GET_INFO_BY_FD_attr.info, bpf_fd);
746 PRINT_FIELD_U(", ", sample_BPF_OBJ_GET_INFO_BY_FD_attr.info, info_len);
747 PRINT_FIELD_X(", ", sample_BPF_OBJ_GET_INFO_BY_FD_attr.info, info);
751 # endif /* HAVE_UNION_BPF_ATTR_INFO_INFO */
756 page_size = get_page_size();
757 end_of_page = (unsigned long) tail_alloc(1) + 1;
759 # ifdef HAVE_UNION_BPF_ATTR_NUMA_NODE
760 TEST_BPF(BPF_MAP_CREATE);
763 # ifdef HAVE_UNION_BPF_ATTR_FLAGS
764 TEST_BPF(BPF_MAP_LOOKUP_ELEM);
765 TEST_BPF(BPF_MAP_UPDATE_ELEM);
766 TEST_BPF(BPF_MAP_DELETE_ELEM);
767 TEST_BPF(BPF_MAP_GET_NEXT_KEY);
770 # ifdef HAVE_UNION_BPF_ATTR_PROG_FLAGS
771 TEST_BPF(BPF_PROG_LOAD);
774 # ifdef HAVE_UNION_BPF_ATTR_BPF_FD
775 TEST_BPF(BPF_OBJ_PIN);
776 TEST_BPF(BPF_OBJ_GET);
779 # ifdef HAVE_UNION_BPF_ATTR_ATTACH_FLAGS
780 TEST_BPF(BPF_PROG_ATTACH);
781 TEST_BPF(BPF_PROG_DETACH);
784 # ifdef HAVE_UNION_BPF_ATTR_TEST_DURATION
785 TEST_BPF(BPF_PROG_TEST_RUN);
788 # ifdef HAVE_UNION_BPF_ATTR_NEXT_ID
789 TEST_BPF(BPF_PROG_GET_NEXT_ID);
790 TEST_BPF(BPF_MAP_GET_NEXT_ID);
791 TEST_BPF(BPF_PROG_GET_FD_BY_ID);
792 TEST_BPF(BPF_MAP_GET_FD_BY_ID);
795 # ifdef HAVE_UNION_BPF_ATTR_INFO_INFO
796 TEST_BPF(BPF_OBJ_GET_INFO_BY_FD);
799 sys_bpf(0xfacefeed, end_of_page, 40);
800 printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n",
801 end_of_page, errstr);
803 puts("+++ exited with 0 +++");
809 SKIP_MAIN_UNDEFINED("__NR_bpf && HAVE_UNION_BPF_ATTR_*")