// SPDX-License-Identifier: GPL-2.0-only #define _GNU_SOURCE #include struct inst { struct bpf_object *obj; struct bpf_link *link; }; static struct bpf_program *load_prog(char *file, char *name, struct inst *inst) { struct bpf_object *obj; struct bpf_program *prog; int err; obj = bpf_object__open_file(file, NULL); if (!ASSERT_OK_PTR(obj, "obj_open_file")) return NULL; inst->obj = obj; err = bpf_object__load(obj); if (!ASSERT_OK(err, "obj_load")) return NULL; prog = bpf_object__find_program_by_name(obj, name); if (!ASSERT_OK_PTR(prog, "obj_find_prog")) return NULL; return prog; } /* TODO: use different target function to run in concurrent mode */ void serial_test_trampoline_count(void) { char *file = "test_trampoline_count.bpf.o"; char *const progs[] = { "fentry_test", "fmod_ret_test", "fexit_test" }; int bpf_max_tramp_links, err, i, prog_fd; struct bpf_program *prog; struct bpf_link *link; struct inst *inst; LIBBPF_OPTS(bpf_test_run_opts, opts); bpf_max_tramp_links = get_bpf_max_tramp_links(); if (!ASSERT_GE(bpf_max_tramp_links, 1, "bpf_max_tramp_links")) return; inst = calloc(bpf_max_tramp_links + 1, sizeof(*inst)); if (!ASSERT_OK_PTR(inst, "inst")) return; /* attach 'allowed' trampoline programs */ for (i = 0; i < bpf_max_tramp_links; i++) { prog = load_prog(file, progs[i % ARRAY_SIZE(progs)], &inst[i]); if (!prog) goto cleanup; link = bpf_program__attach(prog); if (!ASSERT_OK_PTR(link, "attach_prog")) goto cleanup; inst[i].link = link; } /* and try 1 extra.. */ prog = load_prog(file, "fmod_ret_test", &inst[i]); if (!prog) goto cleanup; /* ..that needs to fail */ link = bpf_program__attach(prog); if (!ASSERT_ERR_PTR(link, "attach_prog")) { inst[i].link = link; goto cleanup; } /* with E2BIG error */ if (!ASSERT_EQ(libbpf_get_error(link), -E2BIG, "E2BIG")) goto cleanup; if (!ASSERT_EQ(link, NULL, "ptr_is_null")) goto cleanup; /* and finally execute the probe */ prog_fd = bpf_program__fd(prog); if (!ASSERT_GE(prog_fd, 0, "bpf_program__fd")) goto cleanup; err = bpf_prog_test_run_opts(prog_fd, &opts); if (!ASSERT_OK(err, "bpf_prog_test_run_opts")) goto cleanup; ASSERT_EQ(opts.retval & 0xffff, 33, "bpf_modify_return_test.result"); ASSERT_EQ(opts.retval >> 16, 2, "bpf_modify_return_test.side_effect"); cleanup: for (; i >= 0; i--) { bpf_link__destroy(inst[i].link); bpf_object__close(inst[i].obj); } free(inst); }