/
githubmirror
/
strace
Обзор
Документация
Войти
/
githubmirror
/
strace
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
tests/bpf.c
3 074 строки
93 KB
Dmitry V. Levin
bpf: decode path_fd field of BPF_LINK_CREATE uprobe_multi
08 июл 2026, 11:00
08 июл 2026, 11:00
6ec58d3
Код
Авторство
О чём код?
/* * Check bpf syscall decoding. * * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@strace.io> * Copyright (c) 2015-2026 The strace developers. * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "tests.h" #include <stddef.h> #include <stdio.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include "scno.h" #ifdef HAVE_LINUX_BPF_H # include <linux/bpf.h> #endif #include "bpf_attr.h" #include "print_fields.h" #include "xmalloc.h" #include "xlat.h" #include "xlat/bpf_attach_type.h" #include "xlat/bpf_commands.h" #include "xlat/bpf_map_types.h" #include "xlat/bpf_prog_types.h" #include "xlat/bpf_test_run_flags.h" #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4 # define BIG_ADDR(addr64_, addr32_) addr64_ # define BIG_ADDR_MAYBE(addr_) #elif defined __arm__ || defined __i386__ || defined __mips__ \ || defined __powerpc__ || defined __riscv || defined __s390__ \ || defined __sparc__ || defined __tile__ # define BIG_ADDR(addr64_, addr32_) addr64_ " or " addr32_ # define BIG_ADDR_MAYBE(addr_) addr_ " or " #else # define BIG_ADDR(addr64_, addr32_) addr32_ # define BIG_ADDR_MAYBE(addr_) #endif #ifndef FD0_PATH # define FD0_PATH "" #endif #ifndef HAVE_STRUCT_BPF_INSN struct bpf_insn { uint8_t code; uint8_t dst_reg:4; uint8_t src_reg:4; int16_t off; int32_t imm; }; #endif #define BPF_ATTR_DATA_FIELD(cmd_) struct cmd_ ## _struct cmd_ ## _data union bpf_attr_data { BPF_ATTR_DATA_FIELD(BPF_MAP_CREATE); BPF_ATTR_DATA_FIELD(BPF_MAP_LOOKUP_ELEM); BPF_ATTR_DATA_FIELD(BPF_MAP_UPDATE_ELEM); BPF_ATTR_DATA_FIELD(BPF_MAP_DELETE_ELEM); BPF_ATTR_DATA_FIELD(BPF_MAP_GET_NEXT_KEY); BPF_ATTR_DATA_FIELD(BPF_PROG_LOAD); BPF_ATTR_DATA_FIELD(BPF_OBJ_PIN); BPF_ATTR_DATA_FIELD(BPF_PROG_ATTACH); BPF_ATTR_DATA_FIELD(BPF_PROG_TEST_RUN); BPF_ATTR_DATA_FIELD(BPF_PROG_GET_NEXT_ID); BPF_ATTR_DATA_FIELD(BPF_PROG_GET_FD_BY_ID); BPF_ATTR_DATA_FIELD(BPF_MAP_GET_FD_BY_ID); BPF_ATTR_DATA_FIELD(BPF_OBJ_GET_INFO_BY_FD); BPF_ATTR_DATA_FIELD(BPF_PROG_QUERY); BPF_ATTR_DATA_FIELD(BPF_RAW_TRACEPOINT_OPEN); BPF_ATTR_DATA_FIELD(BPF_BTF_LOAD); BPF_ATTR_DATA_FIELD(BPF_BTF_GET_FD_BY_ID); BPF_ATTR_DATA_FIELD(BPF_TASK_FD_QUERY); BPF_ATTR_DATA_FIELD(BPF_MAP_FREEZE); BPF_ATTR_DATA_FIELD(BPF_MAP_LOOKUP_BATCH); BPF_ATTR_DATA_FIELD(BPF_MAP_UPDATE_BATCH); BPF_ATTR_DATA_FIELD(BPF_MAP_DELETE_BATCH); BPF_ATTR_DATA_FIELD(BPF_LINK_CREATE); BPF_ATTR_DATA_FIELD(BPF_LINK_UPDATE); BPF_ATTR_DATA_FIELD(BPF_LINK_GET_FD_BY_ID); BPF_ATTR_DATA_FIELD(BPF_ENABLE_STATS); BPF_ATTR_DATA_FIELD(BPF_ITER_CREATE); BPF_ATTR_DATA_FIELD(BPF_LINK_DETACH); BPF_ATTR_DATA_FIELD(BPF_PROG_BIND_MAP); BPF_ATTR_DATA_FIELD(BPF_TOKEN_CREATE); BPF_ATTR_DATA_FIELD(BPF_PROG_STREAM_READ_BY_FD); BPF_ATTR_DATA_FIELD(BPF_PROG_ASSOC_STRUCT_OPS); char char_data[256]; }; struct bpf_attr_check { union bpf_attr_data data; size_t size; size_t iters; const char *str; void (*init_fn)(struct bpf_attr_check *check, size_t idx); void (*print_fn)(const struct bpf_attr_check *check, unsigned long addr, size_t idx); }; struct bpf_check { kernel_ulong_t cmd; const char *cmd_str; const struct bpf_attr_check *checks; size_t count; }; static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL; static const char *errstr; static const char *at_fdcwd_str; static const unsigned int sizeof_attr = sizeof(union bpf_attr_data); static unsigned int page_size; static unsigned long end_of_page; static long sys_bpf(kernel_ulong_t cmd, kernel_ulong_t attr, kernel_ulong_t size) { long rc = syscall(__NR_bpf, cmd, attr, size); errstr = sprintrc(rc); #ifdef INJECT_RETVAL if (rc != INJECT_RETVAL) error_msg_and_fail("Got a return value of %ld != %ld", rc, (long) INJECT_RETVAL); static char inj_errstr[4096]; snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr); errstr = inj_errstr; #endif return rc; } #if VERBOSE # define print_extra_data(addr_, offs_, size_) \ do { \ printf("extra_data="); \ print_quoted_hex((addr_) + (offs_), (size_)); \ printf(" /* bytes %u..%u */", (offs_), (size_) + (offs_) - 1); \ } while (0) #else # define print_extra_data(addr_, offs_, size_) printf("...") #endif static void print_bpf_attr(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { if (check->print_fn) check->print_fn(check, addr, idx); else printf("%s", check->str); } static void test_bpf(const struct bpf_check *cmd_check) { const struct bpf_attr_check *check = 0; const union bpf_attr_data *data = 0; unsigned int offset = 0; size_t j = 0; /* zero addr */ sys_bpf(cmd_check->cmd, 0, long_bits | sizeof(union bpf_attr_data)); printf("bpf(%s, NULL, %u) = %s\n", cmd_check->cmd_str, sizeof_attr, errstr); /* zero size */ unsigned long addr = end_of_page - sizeof_attr; sys_bpf(cmd_check->cmd, addr, long_bits); printf("bpf(%s, %#lx, 0) = %s\n", cmd_check->cmd_str, addr, errstr); for (size_t i = 0; i < cmd_check->count; i++) { check = &cmd_check->checks[i]; for (j = 0; j < MAX(check->iters, 1); j++) { if (check->init_fn) check->init_fn((struct bpf_attr_check *) check, j); data = &check->data; offset = check->size; addr = end_of_page - offset; memcpy((void *) addr, data, offset); /* starting piece of bpf_attr_data */ sys_bpf(cmd_check->cmd, addr, offset); printf("bpf(%s, {", cmd_check->cmd_str); print_bpf_attr(check, addr, j); printf("}, %u) = %s\n", offset, errstr); /* short read of the starting piece */ sys_bpf(cmd_check->cmd, addr + 1, offset); printf("bpf(%s, %#lx, %u) = %s\n", cmd_check->cmd_str, addr + 1, offset, errstr); } } j = MAX(check->iters, 1) - 1; if (offset < sizeof_attr) { /* short read of the whole bpf_attr_data */ memcpy((void *) end_of_page - sizeof_attr + 1, data, offset); addr = end_of_page - sizeof_attr + 1; memset((void *) addr + offset, 0, sizeof_attr - offset - 1); sys_bpf(cmd_check->cmd, addr, sizeof_attr); printf("bpf(%s, %#lx, %u) = %s\n", cmd_check->cmd_str, addr, sizeof_attr, errstr); /* the whole bpf_attr_data */ memcpy((void *) end_of_page - sizeof_attr, data, offset); addr = end_of_page - sizeof_attr; memset((void *) addr + offset, 0, sizeof_attr - offset); sys_bpf(cmd_check->cmd, addr, sizeof_attr); printf("bpf(%s, {", cmd_check->cmd_str); print_bpf_attr(check, addr, j); printf("}, %u) = %s\n", sizeof_attr, errstr); /* non-zero bytes after the relevant part */ fill_memory_ex((void *) addr + offset, sizeof_attr - offset, '0', 10); sys_bpf(cmd_check->cmd, addr, sizeof_attr); printf("bpf(%s, {", cmd_check->cmd_str); print_bpf_attr(check, addr, j); printf(", "); print_extra_data((char *) addr, offset, sizeof_attr - offset); printf("}, %u) = %s\n", sizeof_attr, errstr); } /* short read of the whole page */ memcpy((void *) end_of_page - page_size + 1, data, offset); addr = end_of_page - page_size + 1; memset((void *) addr + offset, 0, page_size - offset - 1); sys_bpf(cmd_check->cmd, addr, page_size); printf("bpf(%s, %#lx, %u) = %s\n", cmd_check->cmd_str, addr, page_size, errstr); /* the whole page */ memcpy((void *) end_of_page - page_size, data, offset); addr = end_of_page - page_size; memset((void *) addr + offset, 0, page_size - offset); sys_bpf(cmd_check->cmd, addr, page_size); printf("bpf(%s, {", cmd_check->cmd_str); print_bpf_attr(check, addr, j); printf("}, %u) = %s\n", page_size, errstr); /* non-zero bytes after the whole bpf_attr_data */ fill_memory_ex((void *) addr + offset, page_size - offset, '0', 10); sys_bpf(cmd_check->cmd, addr, page_size); printf("bpf(%s, {", cmd_check->cmd_str); print_bpf_attr(check, addr, j); printf(", "); print_extra_data((char *) addr, offset, page_size - offset); printf("}, %u) = %s\n", page_size, errstr); /* more than a page */ sys_bpf(cmd_check->cmd, addr, page_size + 1); printf("bpf(%s, %#lx, %u) = %s\n", cmd_check->cmd_str, addr, page_size + 1, errstr); } static void init_BPF_MAP_CREATE_attr7(struct bpf_attr_check *check, size_t idx) { struct BPF_MAP_CREATE_struct *attr = &check->data.BPF_MAP_CREATE_data; attr->map_ifindex = ifindex_lo(); } static_assert(ARRAY_SIZE(bpf_map_types_xdata) == 36, "The map_type for tests 1 and 2 below needs to be updated"); static struct bpf_attr_check BPF_MAP_CREATE_checks[] = { { .data = { .BPF_MAP_CREATE_data = { .map_type = 2 } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, map_type), .str = "map_type=BPF_MAP_TYPE_ARRAY, key_size=0, value_size=0" ", max_entries=0" }, { /* 1 */ .data = { .BPF_MAP_CREATE_data = { .map_type = 35, .key_size = 4, .value_size = 8, .max_entries = 256, .map_flags = 63, .inner_map_fd = -1, .numa_node = 3141592653, .map_name = "0123456789abcde", } }, .size = offsetof(struct BPF_MAP_CREATE_struct, map_name) + 8, .str = "map_type=BPF_MAP_TYPE_RHASH, key_size=4" ", value_size=8, max_entries=256" ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NO_COMMON_LRU" "|BPF_F_NUMA_NODE|BPF_F_RDONLY|BPF_F_WRONLY" "|BPF_F_STACK_BUILD_ID" ", inner_map_fd=-1" ", numa_node=3141592653" ", map_name=\"0123456\"...", }, { /* 2 */ .data = { .BPF_MAP_CREATE_data = { .map_type = 36, .key_size = 0xface1e55, .value_size = 0xbadc0ded, .max_entries = 0xbeefcafe, .map_flags = 0xffffc000, .inner_map_fd = 2718281828, .numa_node = -1, .map_name = "", .map_ifindex = 3141592653, } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex), .str = "map_type=0x24 /* BPF_MAP_TYPE_??? */" ", key_size=4207812181, value_size=3134983661" ", max_entries=3203386110" ", map_flags=0xffffc000 /* BPF_F_??? */" ", inner_map_fd=-1576685468" ", map_name=\"\", map_ifindex=3141592653", }, { /* 3 */ .data = { .BPF_MAP_CREATE_data = { .map_type = 0xdeadf00d, .key_size = 0xface1e55, .value_size = 0xbadc0ded, .max_entries = 0xbeefcafe, .map_flags = 0xc0defead, .inner_map_fd = 2718281828, .numa_node = -1, } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, map_flags), .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */" ", key_size=4207812181, value_size=3134983661" ", max_entries=3203386110" ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE" "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID" "|BPF_F_RDONLY_PROG|BPF_F_CLONE" "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS" "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000", }, { /* 4 */ .data = { .BPF_MAP_CREATE_data = { .map_type = 0xdeadf00d, .key_size = 0xface1e55, .value_size = 0xbadc0ded, .max_entries = 0xbeefcafe, .map_flags = 0xc0defead, .inner_map_fd = 2718281828, .numa_node = -1, } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, inner_map_fd), .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */" ", key_size=4207812181, value_size=3134983661" ", max_entries=3203386110" ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE" "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID" "|BPF_F_RDONLY_PROG|BPF_F_CLONE" "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS" "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000" ", inner_map_fd=-1576685468", }, { /* 5 */ .data = { .BPF_MAP_CREATE_data = { .map_type = 0xdeadf00d, .key_size = 0xface1e55, .value_size = 0xbadc0ded, .max_entries = 0xbeefcafe, .map_flags = 0xc0defead, .inner_map_fd = 2718281828, .numa_node = -1, } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, numa_node), .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */" ", key_size=4207812181, value_size=3134983661" ", max_entries=3203386110" ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE" "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID" "|BPF_F_RDONLY_PROG|BPF_F_CLONE" "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS" "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000" ", inner_map_fd=-1576685468" ", numa_node=4294967295 /* NUMA_NO_NODE */", }, { /* 6 */ .data = { .BPF_MAP_CREATE_data = { .map_type = 0xdeadf00d, .key_size = 0xface1e55, .value_size = 0xbadc0ded, .max_entries = 0xbeefcafe, .map_flags = 0xc0defead, .inner_map_fd = 2718281828, .numa_node = -1, .map_name = "fedcba9876543210", } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, map_name), .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */" ", key_size=4207812181, value_size=3134983661" ", max_entries=3203386110" ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE" "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID" "|BPF_F_RDONLY_PROG|BPF_F_CLONE" "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS" "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000" ", inner_map_fd=-1576685468" ", numa_node=4294967295 /* NUMA_NO_NODE */" ", map_name=\"fedcba987654321\"...", }, { /* 7 */ .data = { .BPF_MAP_CREATE_data = { .map_type = 0xdeadf00d, .key_size = 0xface1e55, .value_size = 0xbadc0ded, .max_entries = 0xbeefcafe, .map_flags = 0xc0defead, .inner_map_fd = 2718281828, .numa_node = -1, .map_name = "0123456789abcde", } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex), .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */" ", key_size=4207812181, value_size=3134983661" ", max_entries=3203386110" ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE" "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID" "|BPF_F_RDONLY_PROG|BPF_F_CLONE" "|BPF_F_MMAPABLE|BPF_F_PRESERVE_ELEMS" "|BPF_F_INNER_MAP|BPF_F_LINK|0xc0dec000" ", inner_map_fd=-1576685468" ", numa_node=4294967295 /* NUMA_NO_NODE */" ", map_name=\"0123456789abcde\"" ", map_ifindex=" IFINDEX_LO_STR, .init_fn = init_BPF_MAP_CREATE_attr7, }, { /* 8 */ .data = { .BPF_MAP_CREATE_data = { .btf_fd = 0xbadc0ded, .btf_key_type_id = 0xfacefeed, .btf_value_type_id = 0xcafef00d } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, btf_value_type_id), .str = "map_type=BPF_MAP_TYPE_UNSPEC" ", key_size=0" ", value_size=0" ", max_entries=0" ", map_flags=0" ", inner_map_fd=0" FD0_PATH ", map_name=\"\"" ", map_ifindex=0" ", btf_fd=-1159983635" ", btf_key_type_id=4207869677" ", btf_value_type_id=3405705229" }, { /* 9 */ .data = { .BPF_MAP_CREATE_data = { .btf_fd = 0xbadc0ded, .btf_key_type_id = 0xfacefeed, .btf_value_type_id = 0xcafef00d, .btf_vmlinux_value_type_id = 0xdeadc0de, } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, btf_vmlinux_value_type_id), .str = "map_type=BPF_MAP_TYPE_UNSPEC" ", key_size=0" ", value_size=0" ", max_entries=0" ", map_flags=0" ", inner_map_fd=0" FD0_PATH ", map_name=\"\"" ", map_ifindex=0" ", btf_fd=-1159983635" ", btf_key_type_id=4207869677" ", btf_value_type_id=3405705229" ", btf_vmlinux_value_type_id=3735929054" }, { /* 10 */ .data = { .BPF_MAP_CREATE_data = { .map_type = BPF_MAP_TYPE_BLOOM_FILTER, .map_extra = 4 } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, map_extra), .str = "map_type=BPF_MAP_TYPE_BLOOM_FILTER" ", key_size=0" ", value_size=0" ", max_entries=0" ", map_flags=0" ", inner_map_fd=0" FD0_PATH ", map_name=\"\"" ", map_ifindex=0" ", btf_fd=0" FD0_PATH ", btf_key_type_id=0" ", btf_value_type_id=0" ", btf_vmlinux_value_type_id=0" ", map_extra=4" }, { /* 11 */ .data = { .BPF_MAP_CREATE_data = { .value_type_btf_obj_fd = -1 } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, value_type_btf_obj_fd), .str = "map_type=BPF_MAP_TYPE_UNSPEC" ", key_size=0" ", value_size=0" ", max_entries=0" ", map_flags=0" ", inner_map_fd=0" FD0_PATH ", map_name=\"\"" ", map_ifindex=0" ", btf_fd=0" FD0_PATH ", btf_key_type_id=0" ", btf_value_type_id=0" ", btf_vmlinux_value_type_id=0" ", map_extra=0" ", value_type_btf_obj_fd=-1" }, { /* 12 */ .data = { .BPF_MAP_CREATE_data = { .map_token_fd = -1 } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, map_token_fd), .str = "map_type=BPF_MAP_TYPE_UNSPEC" ", key_size=0" ", value_size=0" ", max_entries=0" ", map_flags=0" ", inner_map_fd=0" FD0_PATH ", map_name=\"\"" ", map_ifindex=0" ", btf_fd=0" FD0_PATH ", btf_key_type_id=0" ", btf_value_type_id=0" ", btf_vmlinux_value_type_id=0" ", map_extra=0" ", value_type_btf_obj_fd=0" FD0_PATH ", map_token_fd=-1" }, { /* 13 */ .data = { .BPF_MAP_CREATE_data = { .excl_prog_hash = 0xdeadbeefbadc0ded, .excl_prog_hash_size = 32 } }, .size = offsetofend(struct BPF_MAP_CREATE_struct, excl_prog_hash_size), .str = "map_type=BPF_MAP_TYPE_UNSPEC" ", key_size=0" ", value_size=0" ", max_entries=0" ", map_flags=0" ", inner_map_fd=0" FD0_PATH ", map_name=\"\"" ", map_ifindex=0" ", btf_fd=0" FD0_PATH ", btf_key_type_id=0" ", btf_value_type_id=0" ", btf_vmlinux_value_type_id=0" ", map_extra=0" ", value_type_btf_obj_fd=0" FD0_PATH ", map_token_fd=0" FD0_PATH ", excl_prog_hash=0xdeadbeefbadc0ded" ", excl_prog_hash_size=32" }, }; static const struct bpf_attr_check BPF_MAP_LOOKUP_ELEM_checks[] = { { .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1 } }, .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, map_fd), .str = "map_fd=-1, key=NULL, value=NULL" }, { .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef, .value = 0xbadc0ded, .flags = 0 } }, .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, flags), .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded" ", flags=BPF_ANY" }, { .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef, .value = 0xbadc0ded, .flags = 4 } }, .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, flags), .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded" ", flags=BPF_F_LOCK" }, { .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef, .value = 0xbadc0ded, .flags = 0x1c } }, .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, flags), .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded" ", flags=BPF_F_ALL_CPUS|BPF_F_CPU|BPF_F_LOCK" }, { .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef, .value = 0xbadc0ded, .flags = -1ULL & ~0x1c } }, .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, flags), .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded" ", flags=0xffffffffffffffe3 /* BPF_??? */" } }; #define BPF_MAP_LOOKUP_AND_DELETE_ELEM_checks BPF_MAP_LOOKUP_ELEM_checks static const struct bpf_attr_check BPF_MAP_UPDATE_ELEM_checks[] = { { .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1 } }, .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, map_fd), .str = "map_fd=-1, key=NULL, value=NULL, flags=BPF_ANY" }, { .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef, .value = 0xbadc0ded, .flags = 0 } }, .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags), .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded" ", flags=BPF_ANY" }, { .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef, .value = 0xbadc0ded, .flags = 2 } }, .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags), .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded" ", flags=BPF_EXIST" }, { .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef, .value = 0xbadc0ded, .flags = 0x1f } }, .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags), .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded" ", flags=BPF_F_ALL_CPUS|BPF_F_CPU|BPF_F_LOCK|BPF_EXIST" "|BPF_NOEXIST" }, { .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef, .value = 0xbadc0ded, .flags = -1ULL & ~0x1f } }, .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags), .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded" ", flags=0xffffffffffffffe0 /* BPF_??? */" } }; static const struct bpf_attr_check BPF_MAP_DELETE_ELEM_checks[] = { { .data = { .BPF_MAP_DELETE_ELEM_data = { .map_fd = -1 } }, .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, map_fd), .str = "map_fd=-1, key=NULL" }, { .data = { .BPF_MAP_DELETE_ELEM_data = { .map_fd = -1, .key = 0xdeadbeef } }, .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, key), .str = "map_fd=-1, key=0xdeadbeef" } }; static const struct bpf_attr_check BPF_MAP_GET_NEXT_KEY_checks[] = { { .data = { .BPF_MAP_GET_NEXT_KEY_data = { .map_fd = -1 } }, .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, map_fd), .str = "map_fd=-1, key=NULL, next_key=NULL" }, { .data = { .BPF_MAP_GET_NEXT_KEY_data = { .map_fd = -1, .key = 0xdeadbeef, .next_key = 0xbadc0ded } }, .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, next_key), .str = "map_fd=-1, key=0xdeadbeef, next_key=0xbadc0ded" } }; static const struct bpf_attr_check BPF_MAP_FREEZE_checks[] = { { .data = { .BPF_MAP_FREEZE_data = { .map_fd = -1 } }, .size = offsetofend(struct BPF_MAP_FREEZE_struct, map_fd), .str = "map_fd=-1" } }; static const struct bpf_insn insns[] = { { .code = 0x95, .dst_reg = 10, .src_reg = 11, .off = 0xdead, .imm = 0xbadc0ded, }, }; static const char license[] = "GPL"; static const char pathname[] = "/sys/fs/bpf/foo/bar"; static char *log_buf; /* * This has to be a macro, otherwise the compiler complains that * initializer element is not constant. */ #define log_buf_size 4096U static char * get_log_buf(void) { if (!log_buf) log_buf = tail_alloc(log_buf_size); return log_buf; } static char * get_log_buf_tail(void) { return get_log_buf() + log_buf_size; } static unsigned char signature_data[] = { 0x30, 0x82, 0x01, 0x0a, /* PKCS#7 signature header */ 0x02, 0x82, 0x01, 0x01, 0x00, 0xab, 0xcd, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xfe, 0xed, }; unsigned char *signature_ptr; #if VERBOSE # define INSNS_FMT \ "[{code=BPF_JMP|BPF_K|BPF_EXIT, dst_reg=BPF_REG_10" \ ", src_reg=0xb /* BPF_REG_??? */, off=%d, imm=%#x}]" # define INSNS_ARG insns[0].off, insns[0].imm #else # define INSNS_FMT "%p" # define INSNS_ARG insns #endif static void init_BPF_PROG_LOAD_attr3(struct bpf_attr_check *check, size_t idx) { struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data; attr->insns = (uintptr_t) insns; attr->license = (uintptr_t) license; attr->log_buf = (uintptr_t) get_log_buf_tail(); } static void print_BPF_PROG_LOAD_attr3(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u" ", insns=" INSNS_FMT ", license=\"%s\", log_level=2718281828" ", log_size=%u, log_buf=%p" ", kern_version=KERNEL_VERSION(51966, 240, 13)" ", prog_flags=0x100 /* BPF_F_??? */" ", prog_name=\"0123456789abcde\"..., prog_ifindex=3203399405", (unsigned int) ARRAY_SIZE(insns), INSNS_ARG, license, log_buf_size, get_log_buf_tail()); } static void init_BPF_PROG_LOAD_attr4(struct bpf_attr_check *check, size_t idx) { struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data; attr->insns = (uintptr_t) insns; attr->license = (uintptr_t) license; attr->log_buf = (uintptr_t) get_log_buf(); attr->prog_ifindex = ifindex_lo(); strncpy(log_buf, "log test", 9); } static void print_BPF_PROG_LOAD_attr4(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=" INSNS_FMT ", license=\"%s\", log_level=2718281828, log_size=4" ", log_buf=\"log \"..." ", kern_version=KERNEL_VERSION(51966, 240, 13)" ", prog_flags=BPF_F_STRICT_ALIGNMENT|BPF_F_ANY_ALIGNMENT" "|BPF_F_TEST_RND_HI32|BPF_F_TEST_STATE_FREQ|BPF_F_SLEEPABLE" "|BPF_F_XDP_HAS_FRAGS|BPF_F_XDP_DEV_BOUND_ONLY" "|BPF_F_TEST_REG_INVARIANTS|0x100" ", prog_name=\"0123456789abcde\"..., prog_ifindex=%s" ", expected_attach_type=BPF_CGROUP_INET6_BIND", (unsigned int) ARRAY_SIZE(insns), INSNS_ARG, license, IFINDEX_LO_STR); } static void init_BPF_PROG_LOAD_attr_signature(struct bpf_attr_check *check, size_t idx) { struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data; if (!signature_ptr) signature_ptr = tail_memdup(signature_data, sizeof(signature_data)); attr->insns = (uintptr_t) insns; attr->license = (uintptr_t) license; attr->signature = (uintptr_t) signature_ptr; attr->signature_size = sizeof(signature_data); attr->keyring_id = 123; } static void print_BPF_PROG_LOAD_attr_signature(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=" INSNS_FMT ", license=\"%s\", log_level=0, log_size=0, log_buf=NULL" ", kern_version=KERNEL_VERSION(0, 0, 0)" ", prog_flags=0, prog_name=\"\", prog_ifindex=0" ", expected_attach_type=BPF_CGROUP_INET_INGRESS" ", prog_btf_fd=0" FD0_PATH ", func_info_rec_size=0, func_info=NULL, func_info_cnt=0" ", line_info_rec_size=0, line_info=NULL, line_info_cnt=0" ", attach_btf_id=0, attach_prog_fd=0" FD0_PATH ", core_relo_cnt=0, fd_array=NULL, core_relos=NULL" ", core_relo_rec_size=0, log_true_size=0" ", prog_token_fd=0" FD0_PATH ", fd_array_cnt=0" ", signature=\"\\x30\\x82\\x01\\x0a\\x02\\x82\\x01\\x01" "\\x00\\xab\\xcd\\xef\\xde\\xad\\xbe\\xef" "\\xca\\xfe\\xba\\xbe\\xfa\\xce\\xfe\\xed\"" ", signature_size=%zu, keyring_id=123", (unsigned int) ARRAY_SIZE(insns), INSNS_ARG, license, sizeof(signature_data)); } static_assert(ARRAY_SIZE(bpf_prog_types_xdata) == 33, "The prog_type for tests 1 and 5 below needs to be updated"); static struct bpf_attr_check BPF_PROG_LOAD_checks[] = { { .data = { .BPF_PROG_LOAD_data = { .prog_type = 1 } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_type), .str = "prog_type=BPF_PROG_TYPE_SOCKET_FILTER" ", insn_cnt=0, insns=NULL, license=NULL" }, { /* 1 */ .data = { .BPF_PROG_LOAD_data = { .prog_type = 33, .insn_cnt = 0xbadc0ded, .insns = 0, .license = 0, .log_level = 42, .log_size = 3141592653U, .log_buf = 0, .kern_version = 0xcafef00d, .prog_flags = 0, } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_flags), .str = "prog_type=0x21 /* BPF_PROG_TYPE_??? */" ", insn_cnt=3134983661, insns=NULL, license=NULL" ", log_level=42, log_size=3141592653, log_buf=NULL" ", kern_version=KERNEL_VERSION(51966, 240, 13)" ", prog_flags=0", }, { /* 2 */ .data = { .BPF_PROG_LOAD_data = { .prog_type = 20, .insn_cnt = 0xbadc0ded, .insns = 0xffffffff00000000, .license = 0xffffffff00000000, .log_level = 2718281828U, .log_size = log_buf_size, .log_buf = 0xffffffff00000000, .kern_version = 0xcafef00d, .prog_flags = 1, .prog_name = "fedcba987654321", } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name), .str = "prog_type=BPF_PROG_TYPE_LIRC_MODE2" ", insn_cnt=3134983661" ", insns=" BIG_ADDR("0xffffffff00000000", "NULL") ", license=" BIG_ADDR("0xffffffff00000000", "NULL") ", log_level=2718281828, log_size=4096" ", log_buf=" BIG_ADDR("0xffffffff00000000", "NULL") ", kern_version=KERNEL_VERSION(51966, 240, 13)" ", prog_flags=BPF_F_STRICT_ALIGNMENT" ", prog_name=\"fedcba987654321\"", }, { /* 3 */ .data = { .BPF_PROG_LOAD_data = { .prog_type = 1, .insn_cnt = ARRAY_SIZE(insns), .log_level = 2718281828U, .log_size = log_buf_size, .kern_version = 0xcafef00d, .prog_flags = 0x100, .prog_name = "0123456789abcdef", .prog_ifindex = 0xbeeffeed, } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_ifindex), .init_fn = init_BPF_PROG_LOAD_attr3, .print_fn = print_BPF_PROG_LOAD_attr3 }, { /* 4 */ .data = { .BPF_PROG_LOAD_data = { .prog_type = 0, .insn_cnt = ARRAY_SIZE(insns), .log_level = 2718281828U, .log_size = 4, .kern_version = 0xcafef00d, .prog_flags = 0x1ff, .prog_name = "0123456789abcdef", .expected_attach_type = 9, } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, expected_attach_type), .init_fn = init_BPF_PROG_LOAD_attr4, .print_fn = print_BPF_PROG_LOAD_attr4 }, { /* 5 */ .data = { .BPF_PROG_LOAD_data = { .prog_type = 32, .insn_cnt = 0xbadc0ded, .insns = 0xffffffff00000000, .license = 0xffffffff00000000, .log_level = 2718281828U, .log_size = log_buf_size, .log_buf = 0xffffffff00000000, .kern_version = 0xcafef00d, .prog_flags = 1, .prog_name = "fedcba987654321", } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name), .str = "prog_type=BPF_PROG_TYPE_NETFILTER" ", insn_cnt=3134983661" ", insns=" BIG_ADDR("0xffffffff00000000", "NULL") ", license=" BIG_ADDR("0xffffffff00000000", "NULL") ", log_level=2718281828, log_size=4096" ", log_buf=" BIG_ADDR("0xffffffff00000000", "NULL") ", kern_version=KERNEL_VERSION(51966, 240, 13)" ", prog_flags=BPF_F_STRICT_ALIGNMENT" ", prog_name=\"fedcba987654321\"", }, { /* 6 */ .data = { .BPF_PROG_LOAD_data = { .prog_flags = 2, .expected_attach_type = 17, .prog_btf_fd = 0xbadc0ded, .func_info_rec_size = 0xdad1bef2, .func_info = 0xfac1fed2fac3fed4, .func_info_cnt = 0xdad3bef4, .line_info_rec_size = 0xdad5bef6, .line_info = 0xfac5fed5fac7fed8, .line_info_cnt = 0xdad7bef8, .attach_btf_id = 0xdad7befa, .attach_prog_fd = 0xbadc0def, .fd_array = 0xfaceb00c, } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, fd_array), .str = "prog_type=BPF_PROG_TYPE_UNSPEC" ", insn_cnt=0" ", insns=NULL" ", license=NULL" ", log_level=0" ", log_size=0" ", log_buf=NULL" ", kern_version=KERNEL_VERSION(0, 0, 0)" ", prog_flags=BPF_F_ANY_ALIGNMENT" ", prog_name=\"\"" ", prog_ifindex=0" ", expected_attach_type=BPF_FLOW_DISSECTOR" ", prog_btf_fd=-1159983635" ", func_info_rec_size=3671178994" ", func_info=0xfac1fed2fac3fed4" ", func_info_cnt=3671310068" ", line_info_rec_size=3671441142" ", line_info=0xfac5fed5fac7fed8" ", line_info_cnt=3671572216" ", attach_btf_id=3671572218" ", attach_prog_fd=-1159983633" ", fd_array=0xfaceb00c" }, { /* 7 */ .data = { .BPF_PROG_LOAD_data = { .core_relo_cnt = 0xfaceb000, .core_relos = 0xdeadbeefbadc0ded, .core_relo_rec_size = 16, } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, core_relo_rec_size), .str = "prog_type=BPF_PROG_TYPE_UNSPEC" ", insn_cnt=0" ", insns=NULL" ", license=NULL" ", log_level=0" ", log_size=0" ", log_buf=NULL" ", kern_version=KERNEL_VERSION(0, 0, 0)" ", prog_flags=0" ", prog_name=\"\"" ", prog_ifindex=0" ", expected_attach_type=BPF_CGROUP_INET_INGRESS" ", prog_btf_fd=0" FD0_PATH ", func_info_rec_size=0" ", func_info=NULL" ", func_info_cnt=0" ", line_info_rec_size=0" ", line_info=NULL" ", line_info_cnt=0" ", attach_btf_id=0" ", attach_prog_fd=0" FD0_PATH ", core_relo_cnt=4207849472" ", fd_array=NULL" ", core_relos=0xdeadbeefbadc0ded" ", core_relo_rec_size=16" }, { /* 8 */ .data = { .BPF_PROG_LOAD_data = { .log_true_size = 4096 } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, log_true_size), .str = "prog_type=BPF_PROG_TYPE_UNSPEC" ", insn_cnt=0" ", insns=NULL" ", license=NULL" ", log_level=0" ", log_size=0" ", log_buf=NULL" ", kern_version=KERNEL_VERSION(0, 0, 0)" ", prog_flags=0" ", prog_name=\"\"" ", prog_ifindex=0" ", expected_attach_type=BPF_CGROUP_INET_INGRESS" ", prog_btf_fd=0" FD0_PATH ", func_info_rec_size=0" ", func_info=NULL" ", func_info_cnt=0" ", line_info_rec_size=0" ", line_info=NULL" ", line_info_cnt=0" ", attach_btf_id=0" ", attach_prog_fd=0" FD0_PATH ", core_relo_cnt=0" ", fd_array=NULL" ", core_relos=NULL" ", core_relo_rec_size=0" ", log_true_size=4096" }, { /* 9 */ .data = { .BPF_PROG_LOAD_data = { .prog_token_fd = -1 } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_token_fd), .str = "prog_type=BPF_PROG_TYPE_UNSPEC" ", insn_cnt=0" ", insns=NULL" ", license=NULL" ", log_level=0" ", log_size=0" ", log_buf=NULL" ", kern_version=KERNEL_VERSION(0, 0, 0)" ", prog_flags=0" ", prog_name=\"\"" ", prog_ifindex=0" ", expected_attach_type=BPF_CGROUP_INET_INGRESS" ", prog_btf_fd=0" FD0_PATH ", func_info_rec_size=0" ", func_info=NULL" ", func_info_cnt=0" ", line_info_rec_size=0" ", line_info=NULL" ", line_info_cnt=0" ", attach_btf_id=0" ", attach_prog_fd=0" FD0_PATH ", core_relo_cnt=0" ", fd_array=NULL" ", core_relos=NULL" ", core_relo_rec_size=0" ", log_true_size=0" ", prog_token_fd=-1" }, { /* 10 */ .data = { .BPF_PROG_LOAD_data = { .fd_array_cnt = 42 } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, fd_array_cnt), .str = "prog_type=BPF_PROG_TYPE_UNSPEC" ", insn_cnt=0" ", insns=NULL" ", license=NULL" ", log_level=0" ", log_size=0" ", log_buf=NULL" ", kern_version=KERNEL_VERSION(0, 0, 0)" ", prog_flags=0" ", prog_name=\"\"" ", prog_ifindex=0" ", expected_attach_type=BPF_CGROUP_INET_INGRESS" ", prog_btf_fd=0" FD0_PATH ", func_info_rec_size=0" ", func_info=NULL" ", func_info_cnt=0" ", line_info_rec_size=0" ", line_info=NULL" ", line_info_cnt=0" ", attach_btf_id=0" ", attach_prog_fd=0" FD0_PATH ", core_relo_cnt=0" ", fd_array=NULL" ", core_relos=NULL" ", core_relo_rec_size=0" ", log_true_size=0" ", prog_token_fd=0" FD0_PATH ", fd_array_cnt=42" }, { /* 11 */ .data = { .BPF_PROG_LOAD_data = { .signature = 0xffffffff00000000, .signature_size = 256, .keyring_id = -1 } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, keyring_id), .str = "prog_type=BPF_PROG_TYPE_UNSPEC" ", insn_cnt=0" ", insns=NULL" ", license=NULL" ", log_level=0" ", log_size=0" ", log_buf=NULL" ", kern_version=KERNEL_VERSION(0, 0, 0)" ", prog_flags=0" ", prog_name=\"\"" ", prog_ifindex=0" ", expected_attach_type=BPF_CGROUP_INET_INGRESS" ", prog_btf_fd=0" FD0_PATH ", func_info_rec_size=0" ", func_info=NULL" ", func_info_cnt=0" ", line_info_rec_size=0" ", line_info=NULL" ", line_info_cnt=0" ", attach_btf_id=0" ", attach_prog_fd=0" FD0_PATH ", core_relo_cnt=0" ", fd_array=NULL" ", core_relos=NULL" ", core_relo_rec_size=0" ", log_true_size=0" ", prog_token_fd=0" FD0_PATH ", fd_array_cnt=0" ", signature=" BIG_ADDR("0xffffffff00000000", "NULL") ", signature_size=256" ", keyring_id=-1" }, { /* 12 */ .data = { .BPF_PROG_LOAD_data = { .insn_cnt = ARRAY_SIZE(insns), .keyring_id = 123 } }, .size = offsetofend(struct BPF_PROG_LOAD_struct, keyring_id), .init_fn = init_BPF_PROG_LOAD_attr_signature, .print_fn = print_BPF_PROG_LOAD_attr_signature, }, }; static void init_BPF_OBJ_PIN_attr(struct bpf_attr_check *check, size_t idx) { struct BPF_OBJ_PIN_struct *attr = &check->data.BPF_OBJ_PIN_data; attr->pathname = (uintptr_t) pathname; } static void init_BPF_OBJ_PIN_str(struct bpf_attr_check *check, size_t idx) { check->str = xasprintf("pathname=NULL, bpf_fd=-1, file_flags=BPF_F_PATH_FD" ", path_fd=%s", at_fdcwd_str); } static struct bpf_attr_check BPF_OBJ_PIN_checks[] = { { .data = { .BPF_OBJ_PIN_data = { .pathname = 0 } }, .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname), .str = "pathname=NULL, bpf_fd=0" FD0_PATH }, { .data = { .BPF_OBJ_PIN_data = { .pathname = 0xFFFFFFFFFFFFFFFFULL } }, .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname), .str = "pathname=" BIG_ADDR("0xffffffffffffffff", "0xffffffff") ", bpf_fd=0" FD0_PATH, }, { .data = { .BPF_OBJ_PIN_data = { .bpf_fd = -1 } }, .size = offsetofend(struct BPF_OBJ_PIN_struct, bpf_fd), .init_fn = init_BPF_OBJ_PIN_attr, .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1" }, { .data = { .BPF_OBJ_PIN_data = { .bpf_fd = -1, .file_flags = 0x18 } }, .size = offsetofend(struct BPF_OBJ_PIN_struct, file_flags), .init_fn = init_BPF_OBJ_PIN_attr, .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1" ", file_flags=BPF_F_RDONLY|BPF_F_WRONLY" }, { .data = { .BPF_OBJ_PIN_data = { .pathname = 0, .bpf_fd = -1, .file_flags = 0x4000, .path_fd = -100 } }, .size = offsetofend(struct BPF_OBJ_PIN_struct, path_fd), .init_fn = init_BPF_OBJ_PIN_str, } }; #define BPF_OBJ_GET_checks BPF_OBJ_PIN_checks static const struct bpf_attr_check BPF_PROG_ATTACH_checks[] = { { .data = { .BPF_PROG_ATTACH_data = { .target_fd = -1 } }, .size = offsetofend(struct BPF_PROG_ATTACH_struct, target_fd), .str = "target_fd=-1, attach_bpf_fd=0" FD0_PATH ", attach_type=BPF_CGROUP_INET_INGRESS, attach_flags=0" }, { .data = { .BPF_PROG_ATTACH_data = { .target_fd = -1, .attach_bpf_fd = -2, .attach_type = 2, .attach_flags = 7 } }, .size = offsetofend(struct BPF_PROG_ATTACH_struct, attach_flags), .str = "target_fd=-1, attach_bpf_fd=-2" ", attach_type=BPF_CGROUP_INET_SOCK_CREATE" ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI" "|BPF_F_REPLACE" }, { .data = { .BPF_PROG_ATTACH_data = { .target_fd = -1, .attach_bpf_fd = -2, .attach_type = 2, .attach_flags = 0xdf80, .replace_bpf_fd = -3, } }, .size = offsetofend(struct BPF_PROG_ATTACH_struct, replace_bpf_fd), .str = "target_fd=-1, attach_bpf_fd=-2" ", attach_type=BPF_CGROUP_INET_SOCK_CREATE" ", attach_flags=0xdf80 /* BPF_F_??? */" ", replace_bpf_fd=-3" }, { .data = { .BPF_PROG_ATTACH_data = { .relative_fd = -1, .expected_revision = 0xdeadbeefcafebabe, } }, .size = offsetofend(struct BPF_PROG_ATTACH_struct, expected_revision), .str = "target_fd=0" FD0_PATH ", attach_bpf_fd=0" FD0_PATH ", attach_type=BPF_CGROUP_INET_INGRESS" ", attach_flags=0" ", replace_bpf_fd=0" FD0_PATH ", relative_fd=-1" ", expected_revision=16045690984503098046" }, { .data = { .BPF_PROG_ATTACH_data = { .target_ifindex = 0xdeadbeef, .attach_type = 0x2e, .attach_flags = 0, .relative_fd = -1, .expected_revision = 0xfacefeed, } }, .size = offsetofend(struct BPF_PROG_ATTACH_struct, expected_revision), .str = "target_ifindex=3735928559" ", attach_bpf_fd=0" FD0_PATH ", attach_type=BPF_TCX_INGRESS" ", attach_flags=0" ", replace_bpf_fd=0" FD0_PATH ", relative_fd=-1" ", expected_revision=4207869677" }, { .data = { .BPF_PROG_ATTACH_data = { .target_fd = -1, .attach_bpf_fd = -2, .attach_type = 0, .attach_flags = 0x20, .replace_bpf_fd = -3, .relative_id = 0xfacefeed, .expected_revision = 0xdeadbeef, } }, .size = offsetofend(struct BPF_PROG_ATTACH_struct, expected_revision), .str = "target_fd=-1, attach_bpf_fd=-2" ", attach_type=BPF_CGROUP_INET_INGRESS" ", attach_flags=BPF_F_ID" ", replace_bpf_fd=-3" ", relative_id=4207869677" ", expected_revision=3735928559" }, }; #define BPF_PROG_DETACH_checks BPF_PROG_ATTACH_checks static const struct bpf_attr_check BPF_PROG_TEST_RUN_checks[] = { { .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1 } }, .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, prog_fd), .str = "test={prog_fd=-1, retval=0, data_size_in=0" ", data_size_out=0, data_in=NULL, data_out=NULL" ", repeat=0, duration=0}" }, { .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1, .retval = 0xfac1fed2, .data_size_in = 0xfac3fed4, .data_size_out = 0xfac5fed6, .data_in = (uint64_t) 0xfacef11dbadc2dedULL, .data_out = (uint64_t) 0xfacef33dbadc4dedULL, .repeat = 0xfac7fed8, .duration = 0xfac9feda } }, .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, duration), .str = "test={prog_fd=-1, retval=4207017682" ", data_size_in=4207148756, data_size_out=4207279830" ", data_in=0xfacef11dbadc2ded" ", data_out=0xfacef33dbadc4ded" ", repeat=4207410904, duration=4207541978}" }, { .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1, .retval = 0xfac1fed2, .data_size_in = 0xfac3fed4, .data_size_out = 0xfac5fed6, .data_in = (uint64_t) 0xfacef11dbadc2dedULL, .data_out = (uint64_t) 0xfacef33dbadc4dedULL, .repeat = 0xfac7fed8, .duration = 0xfac9feda, .ctx_size_in = 0, .ctx_size_out = 0xfacdfede, .ctx_in = (uint64_t) 0xfacef55dbadc6dedULL, } }, .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, ctx_in), .str = "test={prog_fd=-1, retval=4207017682" ", data_size_in=4207148756, data_size_out=4207279830" ", data_in=0xfacef11dbadc2ded" ", data_out=0xfacef33dbadc4ded" ", repeat=4207410904" ", duration=4207541978" ", ctx_size_in=0, ctx_size_out=4207804126" ", ctx_in=0xfacef55dbadc6ded, ctx_out=NULL}" }, { .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1, .retval = 0xfac1fed2, .data_size_in = 0xfac3fed4, .data_size_out = 0xfac5fed6, .data_in = (uint64_t) 0xfacef11dbadc2dedULL, .data_out = (uint64_t) 0xfacef33dbadc4dedULL, .repeat = 0xfac7fed8, .duration = 0xfac9feda, .ctx_size_in = 0xfacbfedc, .ctx_size_out = 0xfacdfede, .ctx_in = (uint64_t) 0xfacef55dbadc6dedULL, .ctx_out = (uint64_t) 0xfacef77dbadc8dedULL, .flags = BPF_F_TEST_RUN_ON_CPU|BPF_F_TEST_XDP_LIVE_FRAMES, .cpu = 0, } }, .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, cpu), .str = "test={prog_fd=-1, retval=4207017682" ", data_size_in=4207148756, data_size_out=4207279830" ", data_in=0xfacef11dbadc2ded" ", data_out=0xfacef33dbadc4ded" ", repeat=4207410904" ", duration=4207541978" ", ctx_size_in=4207673052" ", ctx_size_out=4207804126" ", ctx_in=0xfacef55dbadc6ded" ", ctx_out=0xfacef77dbadc8ded" ", flags=BPF_F_TEST_RUN_ON_CPU|BPF_F_TEST_XDP_LIVE_FRAMES" ", cpu=0}" }, { .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1, .retval = 0xfac1fed2, .data_size_in = 0xfac3fed4, .data_size_out = 0xfac5fed6, .data_in = (uint64_t) 0xfacef11dbadc2dedULL, .data_out = (uint64_t) 0xfacef33dbadc4dedULL, .repeat = 0xfac7fed8, .duration = 0xfac9feda, .ctx_size_in = 0, .ctx_size_out = 0, .ctx_in = 0, .ctx_out = 0, .flags = 0xfffffffc, .cpu = 3141592653, .batch_size = 2718281828, } }, .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, batch_size), .str = "test={prog_fd=-1, retval=4207017682" ", data_size_in=4207148756, data_size_out=4207279830" ", data_in=0xfacef11dbadc2ded" ", data_out=0xfacef33dbadc4ded" ", repeat=4207410904" ", duration=4207541978" ", ctx_size_in=0, ctx_size_out=0" ", ctx_in=NULL, ctx_out=NULL" ", flags=0xfffffffc /* BPF_F_TEST_??? */" ", cpu=3141592653, batch_size=2718281828}" }, }; static const struct bpf_attr_check BPF_PROG_GET_NEXT_ID_checks[] = { { .data = { .BPF_PROG_GET_NEXT_ID_data = { .start_id = 0xdeadbeef } }, .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, start_id), .str = "start_id=3735928559, next_id=0" }, { .data = { .BPF_PROG_GET_NEXT_ID_data = { .start_id = 0xdeadbeef } }, .size = 1, /* 0xde000000 0x000000ef */ .str = "start_id=" BE_LE("3724541952", "239") ", next_id=0" }, { .data = { .BPF_PROG_GET_NEXT_ID_data = { .start_id = 0xbadc0ded, .next_id = 0xcafef00d } }, .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, next_id), .str = "start_id=3134983661, next_id=3405705229" } }; #define BPF_MAP_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks #define BPF_BTF_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks #define BPF_LINK_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks static const struct bpf_attr_check BPF_PROG_GET_FD_BY_ID_checks[] = { { .data = { .BPF_PROG_GET_FD_BY_ID_data = { .prog_id = 0xdeadbeef } }, .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, prog_id), .str = "prog_id=3735928559" } }; static const struct bpf_attr_check BPF_MAP_GET_FD_BY_ID_checks[] = { { .data = { .BPF_MAP_GET_FD_BY_ID_data = { .map_id = 0xdeadbeef } }, .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, map_id), .str = "map_id=3735928559" }, { .data = { .BPF_MAP_GET_FD_BY_ID_data = { .map_id = 0xbadc0ded, .next_id = 0xcafef00d } }, .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, next_id), .str = "map_id=3134983661" }, { .data = { .BPF_MAP_GET_FD_BY_ID_data = { .map_id = 0xbadc0ded, .next_id = 0xcafef00d, .open_flags = 0xffffff27 } }, .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags), .str = "map_id=3134983661, open_flags=0xffffff27 /* BPF_F_??? */" } }; static const struct bpf_attr_check BPF_OBJ_GET_INFO_BY_FD_checks[] = { { .data = { .BPF_OBJ_GET_INFO_BY_FD_data = { .bpf_fd = -1 } }, .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, bpf_fd), .str = "info={bpf_fd=-1, info_len=0, info=NULL}" }, { .data = { .BPF_OBJ_GET_INFO_BY_FD_data = { .bpf_fd = -1, .info_len = 0xdeadbeef, .info = (uint64_t) 0xfacefeedbadc0dedULL } }, .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, info), .str = "info={bpf_fd=-1, info_len=3735928559" ", info=0xfacefeedbadc0ded}" } }; static uint32_t prog_load_ids[] = { 0, 1, 0xffffffff, 2718281828, }; uint32_t *prog_load_ids_ptr; static uint32_t prog_attach_flags_data[] = { 0x1, /* BPF_F_ALLOW_OVERRIDE */ 0x3, /* BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI */ 0x20, /* BPF_F_ID */ 0xbeefca80, /* Unknown flags */ }; uint32_t *prog_attach_flags_ptr; static void init_BPF_PROG_QUERY_attr4(struct bpf_attr_check *check, size_t idx) { struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data; if (!prog_load_ids_ptr) prog_load_ids_ptr = tail_memdup(prog_load_ids, sizeof(prog_load_ids)); attr->prog_ids = (uintptr_t) prog_load_ids_ptr; attr->prog_cnt = ARRAY_SIZE(prog_load_ids); } static void print_BPF_PROG_QUERY_attr4(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("query={target_fd=-1153374643" ", attach_type=0xfeedface /* BPF_??? */" ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c" ", attach_flags=BPF_F_ALLOW_MULTI|BPF_F_REPLACE" "|BPF_F_BEFORE|BPF_F_AFTER|BPF_F_ID|BPF_F_PREORDER|0xbeefca80" #if defined(INJECT_RETVAL) ", prog_ids=[0, 1, 4294967295, 2718281828], prog_cnt=4}" #else ", prog_ids=%p, prog_cnt=4}", prog_load_ids_ptr #endif ); } static void init_BPF_PROG_QUERY_attr5(struct bpf_attr_check *check, size_t idx) { struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data; if (!prog_load_ids_ptr) prog_load_ids_ptr = tail_memdup(prog_load_ids, sizeof(prog_load_ids)); attr->prog_ids = (uintptr_t) prog_load_ids_ptr; attr->prog_cnt = ARRAY_SIZE(prog_load_ids) + 1; } static void print_BPF_PROG_QUERY_attr5(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("query={target_fd=-1153374643" ", attach_type=0xfeedface /* BPF_??? */" ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c" ", attach_flags=BPF_F_ALLOW_MULTI|BPF_F_REPLACE" "|BPF_F_BEFORE|BPF_F_AFTER|BPF_F_ID|BPF_F_PREORDER|0xbeefca80" #if defined(INJECT_RETVAL) ", prog_ids=[0, 1, 4294967295, 2718281828, ... /* %p */]" ", prog_cnt=5}", prog_load_ids_ptr + ARRAY_SIZE(prog_load_ids) #else ", prog_ids=%p, prog_cnt=5}", prog_load_ids_ptr #endif ); } static void init_BPF_PROG_QUERY_attr6(struct bpf_attr_check *check, size_t idx) { struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data; if (!prog_load_ids_ptr) prog_load_ids_ptr = tail_memdup(prog_load_ids, sizeof(prog_load_ids)); if (!prog_attach_flags_ptr) prog_attach_flags_ptr = tail_memdup(prog_attach_flags_data, sizeof(prog_attach_flags_data)); attr->prog_ids = (uintptr_t) prog_load_ids_ptr; attr->prog_attach_flags = (uintptr_t) prog_attach_flags_ptr; attr->prog_cnt = ARRAY_SIZE(prog_attach_flags_data); } static void print_BPF_PROG_QUERY_attr6(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("query={target_fd=-1153374643" ", attach_type=0xfeedface /* BPF_??? */" ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c" ", attach_flags=0xbeefca80 /* BPF_F_??? */" #if defined(INJECT_RETVAL) ", prog_ids=[0, 1, 4294967295, 2718281828], prog_cnt=4" ", prog_attach_flags=[BPF_F_ALLOW_OVERRIDE" ", BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI" ", BPF_F_ID" ", 0xbeefca80 /* BPF_F_??? */]}" #else ", prog_ids=%p, prog_cnt=4, prog_attach_flags=%p}", prog_load_ids_ptr, prog_attach_flags_ptr #endif ); } static void init_BPF_PROG_QUERY_attr7(struct bpf_attr_check *check, size_t idx) { struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data; attr->link_ids = (uintptr_t) prog_load_ids_ptr; attr->link_attach_flags = (uintptr_t) prog_attach_flags_ptr; attr->prog_cnt = ARRAY_SIZE(prog_attach_flags_data); } static void print_BPF_PROG_QUERY_attr7(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("query={target_ifindex=3735928559" ", attach_type=BPF_TCX_INGRESS" ", query_flags=0, attach_flags=0" ", prog_ids=NULL, prog_cnt=4" ", prog_attach_flags=NULL" #if defined(INJECT_RETVAL) ", link_ids=[0, 1, 4294967295, 2718281828]" ", link_attach_flags=[BPF_F_ALLOW_OVERRIDE" ", BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI" ", BPF_F_ID" ", 0xbeefca80 /* BPF_F_??? */]" ", revision=0xfacefeed}" #else ", link_ids=%p, link_attach_flags=%p" ", revision=0xfacefeed}", prog_load_ids_ptr, prog_attach_flags_ptr #endif ); } static struct bpf_attr_check BPF_PROG_QUERY_checks[] = { { .data = { .BPF_PROG_QUERY_data = { .target_fd = -1 } }, .size = offsetofend(struct BPF_PROG_QUERY_struct, target_fd), .str = "query={target_fd=-1" ", attach_type=BPF_CGROUP_INET_INGRESS, query_flags=0" ", attach_flags=0, prog_ids=NULL, prog_cnt=0}", }, { /* 1 */ .data = { .BPF_PROG_QUERY_data = { .target_fd = 3141592653U, .attach_type = 57, .query_flags = 1, .attach_flags = 3, } }, .size = offsetofend(struct BPF_PROG_QUERY_struct, attach_flags), .str = "query={target_fd=-1153374643" ", attach_type=BPF_TRACE_UPROBE_SESSION" ", query_flags=BPF_F_QUERY_EFFECTIVE" ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI" ", prog_ids=NULL, prog_cnt=0}", }, { /* 2 */ .data = { .BPF_PROG_QUERY_data = { .target_fd = 3141592653U, .attach_type = 62, .query_flags = 0xfffffffe, .attach_flags = 0xffffdf80, .prog_ids = 0xffffffffffffffffULL, .prog_cnt = 2718281828, } }, .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt), .str = "query={target_fd=-1153374643" ", attach_type=0x3e /* BPF_??? */" ", query_flags=0xfffffffe /* BPF_F_QUERY_??? */" ", attach_flags=0xffffdf80 /* BPF_F_??? */" ", prog_ids=" BIG_ADDR("0xffffffffffffffff", "0xffffffff") ", prog_cnt=2718281828}", }, { /* 3 */ .data = { .BPF_PROG_QUERY_data = { .target_fd = 3141592653U, .attach_type = 0xfeedface, .query_flags = 0xdeadf00d, .attach_flags = 0xbeef207f, .prog_ids = 0xffffffffffffffffULL, .prog_cnt = 0, } }, .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt), .str = "query={target_fd=-1153374643" ", attach_type=0xfeedface /* BPF_??? */" ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c" ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI" "|BPF_F_REPLACE|BPF_F_BEFORE|BPF_F_AFTER|BPF_F_ID" "|BPF_F_PREORDER|BPF_F_LINK|0xbeef0000" ", prog_ids=" BIG_ADDR_MAYBE("0xffffffffffffffff") "[]" ", prog_cnt=0}", }, { /* 4 */ .data = { .BPF_PROG_QUERY_data = { .target_fd = 3141592653U, .attach_type = 0xfeedface, .query_flags = 0xdeadf00d, .attach_flags = 0xbeefcafe, } }, .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt), .init_fn = init_BPF_PROG_QUERY_attr4, .print_fn = print_BPF_PROG_QUERY_attr4, }, { /* 5 */ .data = { .BPF_PROG_QUERY_data = { .target_fd = 3141592653U, .attach_type = 0xfeedface, .query_flags = 0xdeadf00d, .attach_flags = 0xbeefcafe, } }, .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt), .init_fn = init_BPF_PROG_QUERY_attr5, .print_fn = print_BPF_PROG_QUERY_attr5, }, { /* 6 */ .data = { .BPF_PROG_QUERY_data = { .target_fd = 3141592653U, .attach_type = 0xfeedface, .query_flags = 0xdeadf00d, .attach_flags = 0xbeefca80, } }, .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_attach_flags), .init_fn = init_BPF_PROG_QUERY_attr6, .print_fn = print_BPF_PROG_QUERY_attr6, }, { /* 7 */ .data = { .BPF_PROG_QUERY_data = { .target_ifindex = 0xdeadbeef, .attach_type = 0x2e, .revision = 0xfacefeed, } }, .size = offsetofend(struct BPF_PROG_QUERY_struct, revision), .init_fn = init_BPF_PROG_QUERY_attr7, .print_fn = print_BPF_PROG_QUERY_attr7, }, }; static void init_BPF_RAW_TRACEPOINT_attr2(struct bpf_attr_check *check, size_t idx) { /* TODO: test the 128 byte limit */ static const char tp_name[] = "0123456789qwertyuiop0123456789qwe"; struct BPF_RAW_TRACEPOINT_OPEN_struct *attr = &check->data.BPF_RAW_TRACEPOINT_OPEN_data; attr->name = (uintptr_t) tp_name; } static struct bpf_attr_check BPF_RAW_TRACEPOINT_OPEN_checks[] = { { .data = { .BPF_RAW_TRACEPOINT_OPEN_data = { .name = 0 } }, .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct, name), .str = "raw_tracepoint={name=NULL, prog_fd=0" FD0_PATH "}", }, { /* 1 */ .data = { .BPF_RAW_TRACEPOINT_OPEN_data = { .name = 0xffffffff00000000ULL, .prog_fd = 0xdeadbeef, } }, .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct, prog_fd), .str = "raw_tracepoint=" "{name=" BIG_ADDR("0xffffffff00000000", "NULL") ", prog_fd=-559038737}", }, { .data = { .BPF_RAW_TRACEPOINT_OPEN_data = { .prog_fd = 0xdeadbeef, .cookie = 0xfacefeeddeadbeefULL, } }, .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct, cookie), .init_fn = init_BPF_RAW_TRACEPOINT_attr2, .str = "raw_tracepoint=" "{name=\"0123456789qwertyuiop0123456789qw\"..." ", prog_fd=-559038737, cookie=0xfacefeeddeadbeef}", } }; static void init_BPF_BTF_LOAD_attr(struct bpf_attr_check *check, size_t idx) { static const char sample_btf_data[] = "bPf\0daTum"; static char *btf_data; if (!btf_data) btf_data = tail_memdup(sample_btf_data, sizeof(sample_btf_data) - 1); struct BPF_BTF_LOAD_struct *attr = &check->data.BPF_BTF_LOAD_data; attr->btf = (uintptr_t) btf_data; } static void print_BPF_BTF_LOAD_attr2(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { const struct BPF_BTF_LOAD_struct *attr = &((union bpf_attr_data *) (uintptr_t) addr)->BPF_BTF_LOAD_data; printf("btf=NULL, btf_log_buf=NULL, btf_size=0, btf_log_size=0" ", btf_log_level=0, btf_log_true_size=%u", attr->btf_log_true_size); } static struct bpf_attr_check BPF_BTF_LOAD_checks[] = { { .data = { .BPF_BTF_LOAD_data = { .btf = 0 } }, .size = offsetofend(struct BPF_BTF_LOAD_struct, btf), .str = "btf=NULL, btf_log_buf=NULL, btf_size=0" ", btf_log_size=0, btf_log_level=0" }, { /* 1 */ .data = { .BPF_BTF_LOAD_data = { .btf_log_buf = 0xfacefeeddeadbeefULL, .btf_size = 9, .btf_log_size = -1U, .btf_log_level = 42 } }, .size = offsetofend(struct BPF_BTF_LOAD_struct, btf_log_level), .init_fn = init_BPF_BTF_LOAD_attr, .str = "btf=\"bPf\\0daTum\"" ", btf_log_buf=0xfacefeeddeadbeef" ", btf_size=9" ", btf_log_size=4294967295" ", btf_log_level=42" }, { /* 2 */ .data = { .BPF_BTF_LOAD_data = { .btf_log_true_size = 0xfacefeed } }, .size = offsetofend(struct BPF_BTF_LOAD_struct, btf_log_true_size), .print_fn = print_BPF_BTF_LOAD_attr2 }, { /* 3 */ .data = { .BPF_BTF_LOAD_data = { .btf_token_fd = -1 } }, .size = offsetofend(struct BPF_BTF_LOAD_struct, btf_token_fd), .str = "btf=NULL, btf_log_buf=NULL, btf_size=0, btf_log_size=0" ", btf_log_level=0, btf_log_true_size=0, btf_flags=0" ", btf_token_fd=-1" }, { /* 4 */ .data = { .BPF_BTF_LOAD_data = { .btf_flags = 0x10000 } }, .size = offsetofend(struct BPF_BTF_LOAD_struct, btf_token_fd), .str = "btf=NULL, btf_log_buf=NULL, btf_size=0, btf_log_size=0" ", btf_log_level=0, btf_log_true_size=0" ", btf_flags=BPF_F_TOKEN_FD, btf_token_fd=0" FD0_PATH } }; static const struct bpf_attr_check BPF_BTF_GET_FD_BY_ID_checks[] = { { .data = { .BPF_BTF_GET_FD_BY_ID_data = { .btf_id = 0xdeadbeef } }, .size = offsetofend(struct BPF_BTF_GET_FD_BY_ID_struct, btf_id), .str = "btf_id=3735928559" }, { .data = { .BPF_BTF_GET_FD_BY_ID_data = { .btf_id = 0xbadc0ded, .open_flags = 0xffffff27, .fd_by_id_token_fd = -100 } }, .size = offsetofend(struct BPF_BTF_GET_FD_BY_ID_struct, fd_by_id_token_fd), .str = "btf_id=3134983661" ", open_flags=0xffffff27 /* BPF_F_??? */" ", fd_by_id_token_fd=-100" } }; static const struct bpf_attr_check BPF_TASK_FD_QUERY_checks[] = { { .data = { .BPF_TASK_FD_QUERY_data = { .pid = 1735928559 } }, .size = offsetofend(struct BPF_TASK_FD_QUERY_struct, pid), .str = "task_fd_query={pid=1735928559, fd=0" FD0_PATH ", flags=0, buf_len=0, buf=NULL, prog_id=0" ", fd_type=BPF_FD_TYPE_RAW_TRACEPOINT" ", probe_offset=0, probe_addr=0}" }, { /* 1 */ .data = { .BPF_TASK_FD_QUERY_data = { .pid = 1405705229, .fd = 0xdeadbeef, .flags = 0xfacefeed, .buf_len = 0xdefaced, .buf = 0xfffffffffffffffe, .prog_id = 0xbadc0ded, .fd_type = 5, .probe_offset = 0xfac1fed2fac3fed4, .probe_addr = 0xfac5fed5fac7fed8 } }, .size = offsetofend(struct BPF_TASK_FD_QUERY_struct, probe_addr), .str = "task_fd_query={pid=1405705229" ", fd=-559038737" ", flags=4207869677" ", buf_len=233811181" ", buf=" BIG_ADDR("0xfffffffffffffffe", "0xfffffffe") ", prog_id=3134983661" ", fd_type=BPF_FD_TYPE_URETPROBE" ", probe_offset=0xfac1fed2fac3fed4" ", probe_addr=0xfac5fed5fac7fed8}" } }; static const struct bpf_attr_check BPF_MAP_LOOKUP_BATCH_checks[] = { { .data = { .BPF_MAP_LOOKUP_BATCH_data = { .map_fd = -1 } }, .size = offsetofend(struct BPF_MAP_LOOKUP_BATCH_struct, map_fd ), .str = "batch={in_batch=NULL, out_batch=NULL, keys=NULL" ", values=NULL, count=0, map_fd=-1, elem_flags=BPF_ANY" ", flags=0}" }, { .data = { .BPF_MAP_LOOKUP_BATCH_data = { .in_batch = 0xfacefeed, .out_batch = 0xbadc0ded, .keys = 0xdeadf00d, .values = 0xfffffffe, .count = 3, .map_fd = -1, .elem_flags = 4, .flags = 4 } }, .size = offsetofend(struct BPF_MAP_LOOKUP_BATCH_struct, flags), .str = "batch={in_batch=0xfacefeed, out_batch=0xbadc0ded" ", keys=0xdeadf00d, values=0xfffffffe, count=3" ", map_fd=-1, elem_flags=BPF_F_LOCK, flags=0x4}" }, { .data = { .BPF_MAP_LOOKUP_BATCH_data = { .in_batch = 0xfacefeed, .out_batch = 0xbadc0ded, .keys = 0xdeadf00d, .values = 0xfffffffe, .count = 3, .map_fd = -1, .elem_flags = -1ULL, .flags = 0xff } }, .size = offsetofend(struct BPF_MAP_LOOKUP_BATCH_struct, flags), .str = "batch={in_batch=0xfacefeed, out_batch=0xbadc0ded" ", keys=0xdeadf00d, values=0xfffffffe, count=3, map_fd=-1" ", elem_flags=BPF_F_ALL_CPUS|BPF_F_CPU|BPF_F_LOCK" "|0xffffffffffffffe3" ", flags=0xff}" } }; static const struct bpf_attr_check BPF_MAP_UPDATE_BATCH_checks[] = { { .data = { .BPF_MAP_UPDATE_BATCH_data = { .map_fd = -1 } }, .size = offsetofend(struct BPF_MAP_UPDATE_BATCH_struct, map_fd ), .str = "batch={keys=NULL, values=NULL, count=0, map_fd=-1" ", elem_flags=BPF_ANY, flags=0}" }, { .data = { .BPF_MAP_UPDATE_BATCH_data = { .keys = 0xdeadf00d, .values = 0xfffffffe, .count = 3, .map_fd = -1, .elem_flags = 4, .flags = 4 } }, .size = offsetofend(struct BPF_MAP_UPDATE_BATCH_struct, flags), .str = "batch={keys=0xdeadf00d, values=0xfffffffe, count=3" ", map_fd=-1, elem_flags=BPF_F_LOCK, flags=0x4}" }, { .data = { .BPF_MAP_UPDATE_BATCH_data = { .keys = 0xdeadf00d, .values = 0xfffffffe, .count = 3, .map_fd = -1, .elem_flags = -1ULL, .flags = 0xff } }, .size = offsetofend(struct BPF_MAP_UPDATE_BATCH_struct, flags), .str = "batch={keys=0xdeadf00d, values=0xfffffffe, count=3" ", map_fd=-1" ", elem_flags=BPF_F_ALL_CPUS|BPF_F_CPU|BPF_F_LOCK|BPF_EXIST" "|BPF_NOEXIST|0xffffffffffffffe0" ", flags=0xff}" } }; static const struct bpf_attr_check BPF_MAP_DELETE_BATCH_checks[] = { { .data = { .BPF_MAP_DELETE_BATCH_data = { .map_fd = -1 } }, .size = offsetofend(struct BPF_MAP_DELETE_BATCH_struct, map_fd ), .str = "batch={keys=NULL, count=0, map_fd=-1" ", elem_flags=BPF_ANY, flags=0}" }, { .data = { .BPF_MAP_DELETE_BATCH_data = { .keys = 0xdeadf00d, .count = 3, .map_fd = -1, .elem_flags = 4, .flags = 4 } }, .size = offsetofend(struct BPF_MAP_DELETE_BATCH_struct, flags), .str = "batch={keys=0xdeadf00d, count=3, map_fd=-1" ", elem_flags=BPF_F_LOCK, flags=0x4}" }, { .data = { .BPF_MAP_DELETE_BATCH_data = { .keys = 0xdeadf00d, .count = 3, .map_fd = -1, .elem_flags = -1ULL, .flags = 0xff } }, .size = offsetofend(struct BPF_MAP_DELETE_BATCH_struct, flags), .str = "batch={keys=0xdeadf00d, count=3, map_fd=-1" ", elem_flags=BPF_F_ALL_CPUS|BPF_F_CPU|BPF_F_LOCK" "|0xffffffffffffffe3, flags=0xff}" } }; static bool attach_type_is_ifindex(uint32_t attach_type) { switch (attach_type) { case 37: /* BPF_XDP */ case 46: /* BPF_TCX_INGRESS */ case 47: /* BPF_TCX_EGRESS */ case 54: /* BPF_NETKIT_PRIMARY */ case 55: /* BPF_NETKIT_PEER */ return true; default: return false; } } static void init_BPF_LINK_CREATE_attr1(struct bpf_attr_check *check, size_t idx) { struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data; attr->attach_type = idx; } static void print_BPF_LINK_CREATE_attr1(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { uint32_t attach_type = check->data.BPF_LINK_CREATE_data.attach_type; printf("link_create={prog_fd=-1, %s, attach_type=%s" ", flags=BPF_F_REPLACE}", attach_type_is_ifindex(attach_type) ? "target_ifindex=3735928559" : "target_fd=-559038737", sprintxval(bpf_attach_type, idx, "BPF_???")); } /* Keep sorted */ static const uint8_t special_attach_types[] = { 0 /* BPF_CGROUP_INET_INGRESS */, 1 /* BPF_CGROUP_INET_EGRESS */, 2 /* BPF_CGROUP_INET_SOCK_CREATE */, 3 /* BPF_CGROUP_SOCK_OPS */, 6 /* BPF_CGROUP_DEVICE */, 8 /* BPF_CGROUP_INET4_BIND */, 9 /* BPF_CGROUP_INET6_BIND */, 10 /* BPF_CGROUP_INET4_CONNECT */, 11 /* BPF_CGROUP_INET6_CONNECT */, 12 /* BPF_CGROUP_INET4_POST_BIND */, 13 /* BPF_CGROUP_INET6_POST_BIND */, 14 /* BPF_CGROUP_UDP4_SENDMSG */, 15 /* BPF_CGROUP_UDP6_SENDMSG */, 18 /* BPF_CGROUP_SYSCTL */, 19 /* BPF_CGROUP_UDP4_RECVMSG */, 20 /* BPF_CGROUP_UDP6_RECVMSG */, 21 /* BPF_CGROUP_GETSOCKOPT */, 22 /* BPF_CGROUP_SETSOCKOPT */, 24 /* BPF_TRACE_FENTRY */, 25 /* BPF_TRACE_FEXIT */, 26 /* BPF_MODIFY_RETURN */, 27 /* BPF_LSM_MAC */, 28 /* BPF_TRACE_ITER */, 29 /* BPF_CGROUP_INET4_GETPEERNAME */, 30 /* BPF_CGROUP_INET6_GETPEERNAME */, 31 /* BPF_CGROUP_INET4_GETSOCKNAME */, 32 /* BPF_CGROUP_INET6_GETSOCKNAME */, 34 /* BPF_CGROUP_INET_SOCK_RELEASE */, 41 /* BPF_PERF_EVENT */, 42 /* BPF_TRACE_KPROBE_MULTI */, 45 /* BPF_NETFILTER */, 46 /* BPF_TCX_INGRESS */, 47 /* BPF_TCX_EGRESS */, 48 /* BPF_TRACE_UPROBE_MULTI */, 49 /* BPF_CGROUP_UNIX_CONNECT */, 50 /* BPF_CGROUP_UNIX_SENDMSG */, 51 /* BPF_CGROUP_UNIX_RECVMSG */, 52 /* BPF_CGROUP_UNIX_GETPEERNAME */, 53 /* BPF_CGROUP_UNIX_GETSOCKNAME */, 54 /* BPF_NETKIT_PRIMARY */, 55 /* BPF_NETKIT_PEER */, 58 /* BPF_TRACE_FSESSION */, 59 /* BPF_TRACE_FENTRY_MULTI */, 60 /* BPF_TRACE_FEXIT_MULTI */, 61 /* BPF_TRACE_FSESSION_MULTI */, }; static size_t skip_special_attach_types(size_t idx) { for (size_t i = 0; i < ARRAY_SIZE(special_attach_types) && idx >= special_attach_types[i]; i++, idx++) ; return idx; } static void init_BPF_LINK_CREATE_attr2(struct bpf_attr_check *check, size_t idx) { struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data; idx = skip_special_attach_types(idx); attr->attach_type = idx; check->data.char_data[19] = ' '; check->data.char_data[23] = 'O'; check->data.char_data[27] = 'H'; check->data.char_data[31] = ' '; check->data.char_data[35] = 'H'; check->data.char_data[39] = 'A'; check->data.char_data[43] = 'I'; check->data.char_data[47] = '!'; } static void print_BPF_LINK_CREATE_attr2(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { uint32_t attach_type = check->data.BPF_LINK_CREATE_data.attach_type; idx = skip_special_attach_types(idx); printf("link_create={prog_fd=-1, %s, attach_type=%s" ", flags=BPF_F_ALLOW_OVERRIDE|BPF_F_REPLACE|BPF_F_BEFORE" "|BPF_F_ID|BPF_F_PREORDER|0xbadc0d80}, " #if VERBOSE "extra_data=\"\\x00\\x00\\x00\\x20\\x00\\x00\\x00\\x4f" "\\x00\\x00\\x00\\x48\\x00\\x00\\x00\\x20\\x00\\x00\\x00\\x48" "\\x00\\x00\\x00\\x41\\x00\\x00\\x00\\x49\\x00\\x00\\x00\\x21\"" " /* bytes 16..47 */" #else "..." #endif , attach_type_is_ifindex(attach_type) ? "target_ifindex=3735928559" : "target_fd=-559038737", sprintxval(bpf_attach_type, idx, "BPF_???")); } static const int iter_info_data[] = { 0, 42, 314159265, 0xbadc0ded, -1 }; static int *iter_info_data_p; static void init_BPF_LINK_CREATE_attr7(struct bpf_attr_check *check, size_t idx) { struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data; close(iter_info_data[1]); if (!iter_info_data_p) { iter_info_data_p = tail_memdup(iter_info_data, sizeof(iter_info_data)); } attr->iter_info = (uintptr_t) iter_info_data_p; attr->iter_info_len = ARRAY_SIZE(iter_info_data) + idx; } static void print_BPF_LINK_CREATE_attr7(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("link_create={prog_fd=0" FD0_PATH ", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_ITER, flags=0" ", iter_info=[{map={map_fd=0" FD0_PATH "}}, {map={map_fd=42}}" ", {map={map_fd=314159265}}, {map={map_fd=-1159983635}}" ", {map={map_fd=-1}}"); if (idx) { printf(", ... /* %p */", iter_info_data_p + ARRAY_SIZE(iter_info_data)); } printf("], iter_info_len=%zu}", ARRAY_SIZE(iter_info_data) + idx); } static const char *syms_data[] = { "foo", NULL, "OH\0HAI", "abcdefghijklmnopqrstuvwxyz0123456789" }; static char **syms_data_p; static const uint64_t addrs_data[] = { 0, 1, 0xbadc0ded, 0xfacefeeddeadc0deULL }; static uint64_t *addrs_data_p; static_assert(ARRAY_SIZE(syms_data) == ARRAY_SIZE(addrs_data), "syms_data and addrs_data have to have the same element count"); static void init_BPF_LINK_CREATE_attr12(struct bpf_attr_check *check, size_t idx) { struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data; if (!syms_data_p) syms_data_p = tail_memdup(syms_data, sizeof(syms_data)); if (!addrs_data_p) addrs_data_p = tail_memdup(addrs_data, sizeof(addrs_data)); attr->kprobe_multi.cnt = ARRAY_SIZE(syms_data) + idx; attr->kprobe_multi.syms = (uintptr_t) syms_data_p; attr->kprobe_multi.addrs = (uintptr_t) addrs_data_p; attr->kprobe_multi.cookies = (uintptr_t) addrs_data_p; } static void print_BPF_LINK_CREATE_attr12(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("link_create={prog_fd=0" FD0_PATH ", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_KPROBE_MULTI, flags=0" ", kprobe_multi={flags=BPF_F_KPROBE_MULTI_RETURN|0xfacebeee" ", cnt=%zu", ARRAY_SIZE(syms_data) + idx); printf(", syms=[\"foo\", NULL, \"OH\"" ", \"abcdefghijklmnopqrstuvwxyz012345\"..."); if (idx) printf(", ... /* %p */", syms_data_p + ARRAY_SIZE(syms_data)); for (size_t i = 0; i < 2; i++) { printf("], %s=[0, 0x1, 0xbadc0ded, 0xfacefeeddeadc0de", i ? "cookies" : "addrs"); if (idx) { printf(", ... /* %p */", addrs_data_p + ARRAY_SIZE(addrs_data)); } } printf("]}}"); } static const uint32_t tm_ids_data[] = { 1, 42, 0xfacefeed, 0xbadc0ded }; static uint32_t *tm_ids_data_p; static const uint64_t tm_cookies_data[] = { 0, 0xdeadc0defacecafeULL, 0x123456789abcdef0ULL, 0xfeedface00000001ULL }; static uint64_t *tm_cookies_data_p; static_assert(ARRAY_SIZE(tm_ids_data) == ARRAY_SIZE(tm_cookies_data), "tm_ids_data and tm_cookies_data must have the same count"); static void init_BPF_LINK_CREATE_tracing_multi(struct bpf_attr_check *check, size_t idx) { struct BPF_LINK_CREATE_struct *attr = &check->data.BPF_LINK_CREATE_data; if (!tm_ids_data_p) tm_ids_data_p = tail_memdup(tm_ids_data, sizeof(tm_ids_data)); if (!tm_cookies_data_p) tm_cookies_data_p = tail_memdup(tm_cookies_data, sizeof(tm_cookies_data)); attr->tracing_multi.cnt = ARRAY_SIZE(tm_ids_data) + idx; attr->tracing_multi.ids = (uintptr_t) tm_ids_data_p; attr->tracing_multi.cookies = (uintptr_t) tm_cookies_data_p; } static void print_BPF_LINK_CREATE_tracing_multi(const struct bpf_attr_check *check, unsigned long addr, size_t idx) { printf("link_create={prog_fd=0" FD0_PATH ", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_FENTRY_MULTI, flags=0" ", tracing_multi={ids=[1, 42, 4207869677, 3134983661"); if (idx) { printf(", ... /* %p */", tm_ids_data_p + ARRAY_SIZE(tm_ids_data)); } printf("], cookies=[0, 0xdeadc0defacecafe" ", 0x123456789abcdef0, 0xfeedface00000001"); if (idx) { printf(", ... /* %p */", tm_cookies_data_p + ARRAY_SIZE(tm_cookies_data)); } printf("], cnt=%zu}}", ARRAY_SIZE(tm_ids_data) + idx); } static struct bpf_attr_check BPF_LINK_CREATE_checks[] = { { /* 0 */ .data = { .BPF_LINK_CREATE_data = { .prog_fd = 0, .target_fd = 0 } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, target_fd), .str = "link_create={prog_fd=0" FD0_PATH ", target_fd=0" FD0_PATH ", attach_type=BPF_CGROUP_INET_INGRESS, flags=0}" }, { /* 1 */ .data = { .BPF_LINK_CREATE_data = { .prog_fd = -1, .target_fd = 0xdeadbeef, .flags = 4 } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, flags), .iters = ARRAY_SIZE(bpf_attach_type_xdata), .init_fn = init_BPF_LINK_CREATE_attr1, .print_fn = print_BPF_LINK_CREATE_attr1, }, { /* 2 - all non-special attach_types */ .data = { .BPF_LINK_CREATE_data = { .prog_fd = -1, .target_fd = 0xdeadbeef, .attach_type = 5, .flags = 0xbadc0ded } }, .size = 48, .iters = ARRAY_SIZE(bpf_attach_type_xdata) - ARRAY_SIZE(special_attach_types), .init_fn = init_BPF_LINK_CREATE_attr2, .print_fn = print_BPF_LINK_CREATE_attr2, }, { /* 3 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 0, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, target_btf_id), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_CGROUP_INET_INGRESS, flags=0}" }, { /* 4 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 0, .target_btf_id = 0xfacefeed, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, target_btf_id), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_CGROUP_INET_INGRESS, flags=0" ", target_btf_id=4207869677}" }, { /* 5 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 28, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, iter_info_len), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_ITER, flags=0" ", iter_info=NULL, iter_info_len=0}" }, { /* 6 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 28, .iter_info = 0xffffffff00000000, .iter_info_len = 0xdeadface, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, iter_info_len), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_ITER, flags=0" ", iter_info=" BIG_ADDR("0xffffffff00000000", "NULL") ", iter_info_len=3735943886}" }, { /* 7 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 28, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, iter_info_len), .iters = 2, .init_fn = init_BPF_LINK_CREATE_attr7, .print_fn = print_BPF_LINK_CREATE_attr7, }, { /* 8 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 41, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, perf_event.bpf_cookie), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_PERF_EVENT, flags=0" ", perf_event={bpf_cookie=0}}" }, { /* 9 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 41, .perf_event = { .bpf_cookie = 0xdeadc0defacecafeULL }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, perf_event.bpf_cookie), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_PERF_EVENT, flags=0" ", perf_event={bpf_cookie=0xdeadc0defacecafe}}" }, { /* 10 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 42, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, kprobe_multi.cookies), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_KPROBE_MULTI, flags=0" ", kprobe_multi={flags=0, cnt=0, syms=NULL, addrs=NULL" ", cookies=NULL}}" }, { /* 11 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 42, .kprobe_multi = { .flags = 0xdeadc0de, .cnt = 0xbadfaced, .syms = 0xffffffff00000000, .addrs = 0xffffffff00000000, .cookies = 0xffffffff00000000, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, kprobe_multi.cookies), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_KPROBE_MULTI, flags=0" ", kprobe_multi={flags=0xdeadc0de /* BPF_F_KPROBE_MULTI_??? */" ", cnt=3135220973" ", syms=" BIG_ADDR("0xffffffff00000000", "NULL") ", addrs=" BIG_ADDR("0xffffffff00000000", "NULL") ", cookies=" BIG_ADDR("0xffffffff00000000", "NULL") "}}" }, /* * Note that here we rely on the fact that this attach_type has the * largest de-facto attr_size to get the additional checks performed * with the last check passed. */ { /* 12 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 42, .kprobe_multi = { .flags = 0xfacebeef, } } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, kprobe_multi.cookies), .iters = 2, .init_fn = init_BPF_LINK_CREATE_attr12, .print_fn = print_BPF_LINK_CREATE_attr12, }, /* tracing struct tests */ { /* 13 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 24, /* BPF_TRACE_FENTRY */ } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing.cookie), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_FENTRY, flags=0" ", tracing={target_btf_id=0, cookie=0}}" }, { /* 14 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 25, /* BPF_TRACE_FEXIT */ .tracing = { .target_btf_id = 0xfacefeed, .cookie = 0xdeadc0defacecafe, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing.cookie), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_FEXIT, flags=0" ", tracing={target_btf_id=4207869677" ", cookie=0xdeadc0defacecafe}}" }, { /* 15 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 26, /* BPF_MODIFY_RETURN */ .tracing = { .target_btf_id = 0xfacefeed, .cookie = 0xdeadc0defacecafe, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing.cookie), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_MODIFY_RETURN, flags=0" ", tracing={target_btf_id=4207869677" ", cookie=0xdeadc0defacecafe}}" }, { /* 16 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 27, /* BPF_LSM_MAC */ .tracing = { .target_btf_id = 0xfacefeed, .cookie = 0xdeadc0defacecafe, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing.cookie), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_LSM_MAC, flags=0" ", tracing={target_btf_id=4207869677" ", cookie=0xdeadc0defacecafe}}" }, { /* 17 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 58, /* BPF_TRACE_FSESSION */ .tracing = { .target_btf_id = 0xfacefeed, .cookie = 0xdeadc0defacecafe, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing.cookie), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_FSESSION, flags=0" ", tracing={target_btf_id=4207869677" ", cookie=0xdeadc0defacecafe}}" }, /* netfilter struct tests */ { /* 18 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 45, /* BPF_NETFILTER */ } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, netfilter.flags), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_NETFILTER, flags=0" ", netfilter={pf=0, hooknum=0, priority=0, flags=0}}" }, { /* 19 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 45, /* BPF_NETFILTER */ .netfilter = { .pf = 2, /* NFPROTO_IPV4 */ .hooknum = 1, /* NF_INET_LOCAL_IN */ .priority = -128, .flags = 1, /* BPF_F_NETFILTER_IP_DEFRAG */ }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, netfilter.flags), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_NETFILTER, flags=0" ", netfilter={pf=2, hooknum=1, priority=-128" ", flags=BPF_F_NETFILTER_IP_DEFRAG}}" }, /* tcx struct + target_ifindex tests */ { /* 20 */ .data = { .BPF_LINK_CREATE_data = { .target_ifindex = BE_LE(0xdeadbeef, 0xefbeadde), .attach_type = 46, /* BPF_TCX_INGRESS */ } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tcx.expected_revision), .str = "link_create={prog_fd=0" FD0_PATH ", target_ifindex=" BE_LE("3735928559", "4022250974") ", attach_type=BPF_TCX_INGRESS, flags=0" ", tcx={relative_fd=0" FD0_PATH ", expected_revision=0}}" }, { /* 21 */ .data = { .BPF_LINK_CREATE_data = { .target_ifindex = BE_LE(0xdeadbeef, 0xefbeadde), .attach_type = 47, /* BPF_TCX_EGRESS */ .flags = 0x20, /* BPF_F_ID */ .tcx = { .relative_id = 0xfacefeed, .expected_revision = 0x123456789abcdef0, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tcx.expected_revision), .str = "link_create={prog_fd=0" FD0_PATH ", target_ifindex=" BE_LE("3735928559", "4022250974") ", attach_type=BPF_TCX_EGRESS, flags=BPF_F_ID" ", tcx={relative_id=4207869677" ", expected_revision=0x123456789abcdef0}}" }, /* uprobe_multi struct tests */ { /* 22: old struct size (without path_fd) */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 48, /* BPF_TRACE_UPROBE_MULTI */ } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, uprobe_multi.pid), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_UPROBE_MULTI, flags=0" ", uprobe_multi={path=NULL, offsets=NULL" ", ref_ctr_offsets=NULL, cookies=NULL" ", cnt=0, flags=0, pid=0}}" }, { /* 23 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 48, /* BPF_TRACE_UPROBE_MULTI */ } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, uprobe_multi.path_fd), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_UPROBE_MULTI, flags=0" ", uprobe_multi={path=NULL, offsets=NULL" ", ref_ctr_offsets=NULL, cookies=NULL" ", cnt=0, flags=0, pid=0" ", path_fd=0" FD0_PATH"}}" }, { /* 24 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 48, /* BPF_TRACE_UPROBE_MULTI */ .uprobe_multi = { .path = 0xffffffff00000000, .offsets = 0xffffffff00000001, .ref_ctr_offsets = 0xffffffff00000002, .cookies = 0xffffffff00000003, .cnt = 5, .flags = 1, /* BPF_F_UPROBE_MULTI_RETURN */ .pid = 1735928559, .path_fd = 718425901, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, uprobe_multi.path_fd), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_UPROBE_MULTI, flags=0" ", uprobe_multi={path=" BIG_ADDR("0xffffffff00000000", "NULL") ", offsets=" BIG_ADDR("0xffffffff00000001", "0x1") ", ref_ctr_offsets=" BIG_ADDR("0xffffffff00000002", "0x2") ", cookies=" BIG_ADDR("0xffffffff00000003", "0x3") ", cnt=5, flags=BPF_F_UPROBE_MULTI_RETURN" ", pid=1735928559, path_fd=718425901}}" }, /* netkit struct tests */ { /* 25 */ .data = { .BPF_LINK_CREATE_data = { .target_ifindex = BE_LE(0xdeadbeef, 0xefbeadde), .attach_type = 54, /* BPF_NETKIT_PRIMARY */ } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, netkit.expected_revision), .str = "link_create={prog_fd=0" FD0_PATH ", target_ifindex=" BE_LE("3735928559", "4022250974") ", attach_type=BPF_NETKIT_PRIMARY, flags=0" ", netkit={relative_fd=0" FD0_PATH ", expected_revision=0}}" }, { /* 26 */ .data = { .BPF_LINK_CREATE_data = { .target_ifindex = BE_LE(0xdeadbeef, 0xefbeadde), .attach_type = 55, /* BPF_NETKIT_PEER */ .flags = 0x20, /* BPF_F_ID */ .netkit = { .relative_id = 0xfacefeed, .expected_revision = 0x123456789abcdef0, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, netkit.expected_revision), .str = "link_create={prog_fd=0" FD0_PATH ", target_ifindex=" BE_LE("3735928559", "4022250974") ", attach_type=BPF_NETKIT_PEER, flags=BPF_F_ID" ", netkit={relative_id=4207869677" ", expected_revision=0x123456789abcdef0}}" }, /* cgroup struct tests */ { /* 27 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 0, /* BPF_CGROUP_INET_INGRESS */ .flags = 8, /* BPF_F_BEFORE */ } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, cgroup.expected_revision), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_CGROUP_INET_INGRESS, flags=BPF_F_BEFORE" ", cgroup={relative_fd=0" FD0_PATH ", expected_revision=0}}" }, { /* 28 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 1, /* BPF_CGROUP_INET_EGRESS */ .flags = 0x30, /* BPF_F_AFTER | BPF_F_ID */ .cgroup = { .relative_id = 0xfacefeed, .expected_revision = 0x123456789abcdef0ULL, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, cgroup.expected_revision), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_CGROUP_INET_EGRESS" ", flags=BPF_F_AFTER|BPF_F_ID" ", cgroup={relative_id=4207869677" ", expected_revision=0x123456789abcdef0}}" }, { /* 29 - cgroup without BPF_F_BEFORE/AFTER should use target_btf_id */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 34, /* BPF_CGROUP_INET_SOCK_RELEASE */ .target_btf_id = 0xfacefeed, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, target_btf_id), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_CGROUP_INET_SOCK_RELEASE, flags=0" ", target_btf_id=4207869677}" }, { /* 30 - tracing_multi with cnt=0 */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 59, /* BPF_TRACE_FENTRY_MULTI */ .tracing_multi = { .cnt = 0, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing_multi.cnt), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_FENTRY_MULTI, flags=0" ", tracing_multi={ids=NULL, cookies=NULL, cnt=0}}" }, { /* 31 - tracing_multi with arrays */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 59, /* BPF_TRACE_FENTRY_MULTI */ } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing_multi.cnt), .iters = 2, .init_fn = init_BPF_LINK_CREATE_tracing_multi, .print_fn = print_BPF_LINK_CREATE_tracing_multi, }, { /* 32 - BPF_TRACE_FEXIT_MULTI */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 60, /* BPF_TRACE_FEXIT_MULTI */ .tracing_multi = { .cnt = 0, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing_multi.cnt), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_FEXIT_MULTI, flags=0" ", tracing_multi={ids=NULL, cookies=NULL, cnt=0}}" }, { /* 33 - BPF_TRACE_FSESSION_MULTI */ .data = { .BPF_LINK_CREATE_data = { .attach_type = 61, /* BPF_TRACE_FSESSION_MULTI */ .tracing_multi = { .cnt = 0, }, } }, .size = offsetofend(struct BPF_LINK_CREATE_struct, tracing_multi.cnt), .str = "link_create={prog_fd=0" FD0_PATH", target_fd=0" FD0_PATH ", attach_type=BPF_TRACE_FSESSION_MULTI, flags=0" ", tracing_multi={ids=NULL, cookies=NULL, cnt=0}}" }, }; static const struct bpf_attr_check BPF_LINK_UPDATE_checks[] = { { .data = { .BPF_LINK_UPDATE_data = { .link_fd = -1, .new_prog_fd = -2 } }, .size = offsetofend(struct BPF_LINK_UPDATE_struct, old_prog_fd), .str = "link_update={link_fd=-1, new_prog_fd=-2, flags=0}" }, { .data = { .BPF_LINK_UPDATE_data = { .link_fd = -1, .new_prog_fd = 0xdeadbeef, .flags = 4, .old_prog_fd = 0xdeadf00d } }, .size = offsetofend(struct BPF_LINK_UPDATE_struct, old_prog_fd), .str = "link_update={link_fd=-1, new_prog_fd=-559038737" ", flags=BPF_F_REPLACE, old_prog_fd=-559026163}" } }; static const struct bpf_attr_check BPF_LINK_GET_FD_BY_ID_checks[] = { { .data = { .BPF_LINK_GET_FD_BY_ID_data = { .link_id = 0xdeadbeef } }, .size = offsetofend(struct BPF_LINK_GET_FD_BY_ID_struct, link_id), .str = "link_id=3735928559" } }; static const struct bpf_attr_check BPF_ENABLE_STATS_checks[] = { { .data = { .BPF_ENABLE_STATS_data = { .type = 0 } }, .size = offsetofend(struct BPF_ENABLE_STATS_struct, type), .str = "enable_stats={type=BPF_STATS_RUN_TIME}" }, { .data = { .BPF_ENABLE_STATS_data = { .type = 1 } }, .size = offsetofend(struct BPF_ENABLE_STATS_struct, type), .str = "enable_stats={type=0x1 /* BPF_STATS_??? */}" } }; static const struct bpf_attr_check BPF_ITER_CREATE_checks[] = { { .data = { .BPF_ITER_CREATE_data = { .link_fd = -1, .flags = 0 } }, .size = offsetofend(struct BPF_ITER_CREATE_struct, flags), .str = "iter_create={link_fd=-1, flags=0}" }, { .data = { .BPF_ITER_CREATE_data = { .link_fd = -1, .flags = -1U, } }, .size = offsetofend(struct BPF_ITER_CREATE_struct, flags), .str = "iter_create={link_fd=-1, flags=0xffffffff}" } }; static const struct bpf_attr_check BPF_LINK_DETACH_checks[] = { { .data = { .BPF_LINK_DETACH_data = { .link_fd = -1 } }, .size = offsetofend(struct BPF_LINK_DETACH_struct, link_fd), .str = "link_detach={link_fd=-1}" } }; static const struct bpf_attr_check BPF_PROG_BIND_MAP_checks[] = { { .data = { .BPF_PROG_BIND_MAP_data = { .prog_fd = -1, .map_fd = -2, .flags = 0 } }, .size = offsetofend(struct BPF_PROG_BIND_MAP_struct, flags), .str = "prog_bind_map={prog_fd=-1, map_fd=-2, flags=0}" }, { .data = { .BPF_PROG_BIND_MAP_data = { .prog_fd = -1, .map_fd = -2, .flags = -1U, } }, .size = offsetofend(struct BPF_PROG_BIND_MAP_struct, flags), .str = "prog_bind_map={prog_fd=-1, map_fd=-2, flags=0xffffffff}" } }; static const struct bpf_attr_check BPF_TOKEN_CREATE_checks[] = { { .data = { .BPF_TOKEN_CREATE_data = { .flags = 0, .bpffs_fd = -1 } }, .size = offsetofend(struct BPF_TOKEN_CREATE_struct, bpffs_fd), .str = "token_create={flags=0, bpffs_fd=-1}" }, { .data = { .BPF_TOKEN_CREATE_data = { .flags = -1U, .bpffs_fd = -2 } }, .size = offsetofend(struct BPF_TOKEN_CREATE_struct, bpffs_fd), .str = "token_create={flags=0xffffffff, bpffs_fd=-2}" } }; static const struct bpf_attr_check BPF_PROG_ASSOC_STRUCT_OPS_checks[] = { { .data = { .BPF_PROG_ASSOC_STRUCT_OPS_data = { .prog_assoc_struct_ops = { .map_fd = -1, .prog_fd = -2, .flags = 0 } } }, .size = offsetofend(struct BPF_PROG_ASSOC_STRUCT_OPS_struct, prog_assoc_struct_ops), .str = "prog_assoc_struct_ops={map_fd=-1, prog_fd=-2, flags=0}" }, { .data = { .BPF_PROG_ASSOC_STRUCT_OPS_data = { .prog_assoc_struct_ops = { .map_fd = -1, .prog_fd = -2, .flags = -1U, } } }, .size = offsetofend(struct BPF_PROG_ASSOC_STRUCT_OPS_struct, prog_assoc_struct_ops), .str = "prog_assoc_struct_ops={map_fd=-1, prog_fd=-2, flags=0xffffffff}" } }; static void init_BPF_PROG_STREAM_READ_BY_FD_attr(struct bpf_attr_check *check, size_t idx) { static const char sample_data[] = "bPf\0daTum"; static char *data; if (!data) data = tail_memdup(sample_data, sizeof(sample_data) - 1); struct BPF_PROG_STREAM_READ_BY_FD_struct *attr = &check->data.BPF_PROG_STREAM_READ_BY_FD_data; attr->stream_buf = (uintptr_t) data; } static struct bpf_attr_check BPF_PROG_STREAM_READ_BY_FD_checks[] = { { .data = { .BPF_PROG_STREAM_READ_BY_FD_data = { .prog_fd = -1, } }, .size = offsetofend(struct BPF_PROG_STREAM_READ_BY_FD_struct, prog_fd), .str = "prog_stream_read={stream_buf=NULL, stream_buf_len=0" ", stream_id=0, prog_fd=-1}" }, { .data = { .BPF_PROG_STREAM_READ_BY_FD_data = { .stream_buf_len = 9, .stream_id = 0xdeadbeef, .prog_fd = 0, } }, .size = offsetofend(struct BPF_PROG_STREAM_READ_BY_FD_struct, prog_fd), .init_fn = init_BPF_PROG_STREAM_READ_BY_FD_attr, .str = "prog_stream_read={stream_buf=\"bPf\\0daTum\"" ", stream_buf_len=9, stream_id=3735928559" ", prog_fd=0" FD0_PATH "}" } }; #define CHK(cmd_) \ { \ cmd_, #cmd_, \ cmd_##_checks, ARRAY_SIZE(cmd_##_checks), \ } \ /* End of CHK definition */ int main(void) { static const struct bpf_check checks[] = { CHK(BPF_MAP_CREATE), CHK(BPF_MAP_LOOKUP_ELEM), CHK(BPF_MAP_UPDATE_ELEM), CHK(BPF_MAP_DELETE_ELEM), CHK(BPF_MAP_GET_NEXT_KEY), CHK(BPF_PROG_LOAD), CHK(BPF_OBJ_PIN), CHK(BPF_OBJ_GET), CHK(BPF_PROG_ATTACH), CHK(BPF_PROG_DETACH), CHK(BPF_PROG_TEST_RUN), CHK(BPF_PROG_GET_NEXT_ID), CHK(BPF_MAP_GET_NEXT_ID), CHK(BPF_PROG_GET_FD_BY_ID), CHK(BPF_MAP_GET_FD_BY_ID), CHK(BPF_OBJ_GET_INFO_BY_FD), CHK(BPF_PROG_QUERY), CHK(BPF_RAW_TRACEPOINT_OPEN), CHK(BPF_BTF_LOAD), CHK(BPF_BTF_GET_FD_BY_ID), CHK(BPF_TASK_FD_QUERY), CHK(BPF_MAP_LOOKUP_AND_DELETE_ELEM), CHK(BPF_MAP_FREEZE), CHK(BPF_BTF_GET_NEXT_ID), CHK(BPF_MAP_LOOKUP_BATCH), CHK(BPF_MAP_UPDATE_BATCH), CHK(BPF_MAP_DELETE_BATCH), CHK(BPF_LINK_CREATE), CHK(BPF_LINK_UPDATE), CHK(BPF_LINK_GET_NEXT_ID), CHK(BPF_LINK_GET_FD_BY_ID), CHK(BPF_ENABLE_STATS), CHK(BPF_ITER_CREATE), CHK(BPF_LINK_DETACH), CHK(BPF_PROG_BIND_MAP), CHK(BPF_TOKEN_CREATE), CHK(BPF_PROG_STREAM_READ_BY_FD), CHK(BPF_PROG_ASSOC_STRUCT_OPS), }; page_size = get_page_size(); end_of_page = (unsigned long) tail_alloc(1) + 1; at_fdcwd_str = #ifdef YFLAG xasprintf("AT_FDCWD<%s>", get_fd_path(get_dir_fd("."))); #else "AT_FDCWD"; #endif for (size_t i = 0; i < ARRAY_SIZE(checks); i++) test_bpf(checks + i); sys_bpf(0xfacefeed, 0, (kernel_ulong_t) 0xfacefeedbadc0dedULL); printf("bpf(0xfacefeed /* BPF_??? */, NULL, %u) = %s\n", 0xbadc0dedu, errstr); sys_bpf(0xfacefeed, end_of_page, 40); printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n", end_of_page, errstr); puts("+++ exited with 0 +++"); return 0; }