On 25/03/18 01:56PM, Yonghong Song wrote: > > > On 3/18/25 7:33 AM, Anton Protopopov wrote: > > Tests are split in two parts. > > > > The `bpf_insn_set_ops` test checks that the map is managed properly: > > > > * Incorrect instruction indexes are rejected > > * Non-sorted and non-unique indexes are rejected > > * Unfrozen maps are not accepted > > * Two programs can't use the same map > > * BPF progs can't operate the map > > > > The `bpf_insn_set_reloc` part validates, as best as it can do it from user > > space, that instructions are relocated properly: > > > > * no relocations => map is the same > > * expected relocations when instructions are added > > * expected relocations when instructions are deleted > > * expected relocations when multiple functions are present > > > > Signed-off-by: Anton Protopopov <aspsk@xxxxxxxxxxxxx> > > --- > > .../selftests/bpf/prog_tests/bpf_insn_set.c | 639 ++++++++++++++++++ > > 1 file changed, 639 insertions(+) > > create mode 100644 tools/testing/selftests/bpf/prog_tests/bpf_insn_set.c > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_insn_set.c b/tools/testing/selftests/bpf/prog_tests/bpf_insn_set.c > > new file mode 100644 > > index 000000000000..796980bd4fcb > > --- /dev/null > > +++ b/tools/testing/selftests/bpf/prog_tests/bpf_insn_set.c > > @@ -0,0 +1,639 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +#include <bpf/bpf.h> > > +#include <test_progs.h> > > + > > +static inline int map_create(__u32 map_type, __u32 max_entries) > > +{ > > + const char *map_name = "insn_set"; > > + __u32 key_size = 4; > > + __u32 value_size = 4; > > + > > + return bpf_map_create(map_type, map_name, key_size, value_size, max_entries, NULL); > > +} > > + > > +/* > > + * Load a program, which will not be anyhow mangled by the verifier. Add an > > + * insn_set map pointing to every instruction. Check that it hasn't changed > > + * after the program load. > > + */ > > +static void check_one_to_one_mapping(void) > > +{ > > + struct bpf_insn insns[] = { > > + BPF_MOV64_IMM(BPF_REG_0, 4), > > + BPF_MOV64_IMM(BPF_REG_0, 3), > > + BPF_MOV64_IMM(BPF_REG_0, 2), > > + BPF_MOV64_IMM(BPF_REG_0, 1), > > + BPF_MOV64_IMM(BPF_REG_0, 0), > > + BPF_EXIT_INSN(), > > + }; > > + int prog_fd, map_fd; > > prog_fd needs to be initialized to something like -1. Thanks! I've fixed this and similar occurrences. Also replaced syscall(BPF_PROG_LOAD) with libbpf wrappers, so the code is a bit shorter now. Will resend the patch to this thread shortly. > > + union bpf_attr attr = { > > + .prog_type = BPF_PROG_TYPE_XDP, /* we don't care */ > > + .insns = ptr_to_u64(insns), > > + .insn_cnt = ARRAY_SIZE(insns), > > + .license = ptr_to_u64("GPL"), > > + .fd_array = ptr_to_u64(&map_fd), > > + .fd_array_cnt = 1, > > + }; > > + int i; > > + > > + map_fd = map_create(BPF_MAP_TYPE_INSN_SET, ARRAY_SIZE(insns)); > > + if (!ASSERT_GE(map_fd, 0, "map_create")) > > + return; > > + > > + for (i = 0; i < ARRAY_SIZE(insns); i++) > > + if (!ASSERT_EQ(bpf_map_update_elem(map_fd, &i, &i, 0), 0, "bpf_map_update_elem")) > > + goto cleanup; > > Otherwise, goto cleanup here will goto cleanup and close(prog_fd) will close > a random prog_fd. Please check the rest of prog_fd usage. > > > + > > + if (!ASSERT_EQ(bpf_map_freeze(map_fd), 0, "bpf_map_freeze")) > > + return; > > + > > + prog_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); > > + if (!ASSERT_GE(prog_fd, 0, "bpf(BPF_PROG_LOAD)")) > > + goto cleanup; > > + > > + for (i = 0; i < ARRAY_SIZE(insns); i++) { > > + __u32 val; > > + > > + if (!ASSERT_EQ(bpf_map_lookup_elem(map_fd, &i, &val), 0, "bpf_map_lookup_elem")) > > + goto cleanup; > > + > > + ASSERT_EQ(val, i, "val should be equal i"); > > + } > > + > > +cleanup: > > + close(prog_fd); > > + close(map_fd); > > +} > > + > > [...] >