| @@ -1,126 +1,94 @@ |
| 1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | #define _GNU_SOURCE | 2 | #define _GNU_SOURCE |
| 3 | #include <sched.h> | | |
| 4 | #include <sys/prctl.h> | | |
| 5 | #include <test_progs.h> | 3 | #include <test_progs.h> |
| 6 | | 4 | |
| 7 | #define MAX_TRAMP_PROGS 38 | 5 | #define MAX_TRAMP_PROGS 38 |
| 8 | | 6 | |
| 9 | struct inst { | 7 | struct inst { |
| 10 | struct bpf_object *obj; | 8 | struct bpf_object *obj; |
| 11 | struct bpf_link *link_fentry; | 9 | struct bpf_link *link; |
| 12 | struct bpf_link *link_fexit; | | |
| 13 | }; | 10 | }; |
| 14 | | 11 | |
| 15 | static int test_task_rename(void) | 12 | static struct bpf_program *load_prog(char *file, char *name, struct inst *inst) |
| 16 | { | | |
| 17 | int fd, duration = 0, err; | | |
| 18 | char buf[] = "test_overhead"; | | |
| 19 | | | |
| 20 | fd = open("/proc/self/comm", O_WRONLY|O_TRUNC); | | |
| 21 | if (CHECK(fd < 0, "open /proc", "err %d", errno)) | | |
| 22 | return -1; | | |
| 23 | err = write(fd, buf, sizeof(buf)); | | |
| 24 | if (err < 0) { | | |
| 25 | CHECK(err < 0, "task rename", "err %d", errno); | | |
| 26 | close(fd); | | |
| 27 | return -1; | | |
| 28 | } | | |
| 29 | close(fd); | | |
| 30 | return 0; | | |
| 31 | } | | |
| 32 | | | |
| 33 | static struct bpf_link *load(struct bpf_object *obj, const char *name) | | |
| 34 | { | 13 | { |
| | 14 | struct bpf_object *obj; |
| 35 | struct bpf_program *prog; | 15 | struct bpf_program *prog; |
| 36 | int duration = 0; | 16 | int err; |
| | 17 | |
| | 18 | obj = bpf_object__open_file(file, NULL); |
| | 19 | if (!ASSERT_OK_PTR(obj, "obj_open_file")) |
| | 20 | return NULL; |
| | 21 | |
| | 22 | inst->obj = obj; |
| | 23 | |
| | 24 | err = bpf_object__load(obj); |
| | 25 | if (!ASSERT_OK(err, "obj_load")) |
| | 26 | return NULL; |
| 37 | | 27 | |
| 38 | prog = bpf_object__find_program_by_name(obj, name); | 28 | prog = bpf_object__find_program_by_name(obj, name); |
| 39 | if (CHECK(!prog, "find_probe", "prog '%s' not found\n", name)) | 29 | if (!ASSERT_OK_PTR(prog, "obj_find_prog")) |
| 40 | return ERR_PTR(-EINVAL); | 30 | return NULL; |
| 41 | return bpf_program__attach_trace(prog); | 31 | |
| | 32 | return prog; |
| 42 | } | 33 | } |
| 43 | | 34 | |
| 44 | /* TODO: use different target function to run in concurrent mode */ | 35 | /* TODO: use different target function to run in concurrent mode */ |
| 45 | void serial_test_trampoline_count(void) | 36 | void serial_test_trampoline_count(void) |
| 46 | { | 37 | { |
| 47 | const char *fentry_name = "prog1"; | 38 | char *file = "test_trampoline_count.o"; |
| 48 | const char *fexit_name = "prog2"; | 39 | char *const progs[] = { "fentry_test", "fmod_ret_test", "fexit_test" }; |
| 49 | const char *object = "test_trampoline_count.o"; | 40 | struct inst inst[MAX_TRAMP_PROGS + 1] = {}; |
| 50 | struct inst inst[MAX_TRAMP_PROGS] = {}; | 41 | struct bpf_program *prog; |
| 51 | int err, i = 0, duration = 0; | | |
| 52 | struct bpf_object *obj; | | |
| 53 | struct bpf_link *link; | 42 | struct bpf_link *link; |
| 54 | char comm[16] = {}; | 43 | int prog_fd, err, i; |
| | 44 | LIBBPF_OPTS(bpf_test_run_opts, opts); |
| 55 | | 45 | |
| 56 | /* attach 'allowed' trampoline programs */ | 46 | /* attach 'allowed' trampoline programs */ |
| 57 | for (i = 0; i < MAX_TRAMP_PROGS; i++) { | 47 | for (i = 0; i < MAX_TRAMP_PROGS; i++) { |
| 58 | obj = bpf_object__open_file(object, NULL); | 48 | prog = load_prog(file, progs[i % ARRAY_SIZE(progs)], &inst[i]); |
| 59 | if (!ASSERT_OK_PTR(obj, "obj_open_file")) { | 49 | if (!prog) |
| 60 | obj = NULL; | | |
| 61 | goto cleanup; | 50 | goto cleanup; |
| 62 | } | | |
| 63 | | 51 | |
| 64 | err = bpf_object__load(obj); | 52 | link = bpf_program__attach(prog); |
| 65 | if (CHECK(err, "obj_load", "err %d\n", err)) | 53 | if (!ASSERT_OK_PTR(link, "attach_prog")) |
| 66 | goto cleanup; | 54 | goto cleanup; |
| 67 | inst[i].obj = obj; | 55 | |
| 68 | obj = NULL; | 56 | inst[i].link = link; |
| 69 | | | |
| 70 | if (rand() % 2) { | | |
| 71 | link = load(inst[i].obj, fentry_name); | | |
| 72 | if (!ASSERT_OK_PTR(link, "attach_prog")) { | | |
| 73 | link = NULL; | | |
| 74 | goto cleanup; | | |
| 75 | } | | |
| 76 | inst[i].link_fentry = link; | | |
| 77 | } else { | | |
| 78 | link = load(inst[i].obj, fexit_name); | | |
| 79 | if (!ASSERT_OK_PTR(link, "attach_prog")) { | | |
| 80 | link = NULL; | | |
| 81 | goto cleanup; | | |
| 82 | } | | |
| 83 | inst[i].link_fexit = link; | | |
| 84 | } | | |
| 85 | } | 57 | } |
| 86 | | 58 | |
| 87 | /* and try 1 extra.. */ | 59 | /* and try 1 extra.. */ |
| 88 | obj = bpf_object__open_file(object, NULL); | 60 | prog = load_prog(file, "fmod_ret_test", &inst[i]); |
| 89 | if (!ASSERT_OK_PTR(obj, "obj_open_file")) { | 61 | if (!prog) |
| 90 | obj = NULL; | | |
| 91 | goto cleanup; | 62 | goto cleanup; |
| 92 | } | | |
| 93 | | | |
| 94 | err = bpf_object__load(obj); | | |
| 95 | if (CHECK(err, "obj_load", "err %d\n", err)) | | |
| 96 | goto cleanup_extra; | | |
| 97 | | 63 | |
| 98 | /* ..that needs to fail */ | 64 | /* ..that needs to fail */ |
| 99 | link = load(obj, fentry_name); | 65 | link = bpf_program__attach(prog); |
| 100 | err = libbpf_get_error(link); | 66 | if (!ASSERT_ERR_PTR(link, "attach_prog")) { |
| 101 | if (!ASSERT_ERR_PTR(link, "cannot attach over the limit")) { | 67 | inst[i].link = link; |
| 102 | bpf_link__destroy(link); | 68 | goto cleanup; |
| 103 | goto cleanup_extra; | | |
| 104 | } | 69 | } |
| 105 | | 70 | |
| 106 | /* with E2BIG error */ | 71 | /* with E2BIG error */ |
| 107 | ASSERT_EQ(err, -E2BIG, "proper error check"); | 72 | if (!ASSERT_EQ(libbpf_get_error(link), -E2BIG, "E2BIG")) |
| 108 | ASSERT_EQ(link, NULL, "ptr_is_null"); | 73 | goto cleanup; |
| | 74 | if (!ASSERT_EQ(link, NULL, "ptr_is_null")) |
| | 75 | goto cleanup; |
| 109 | | 76 | |
| 110 | /* and finaly execute the probe */ | 77 | /* and finaly execute the probe */ |
| 111 | if (CHECK_FAIL(prctl(PR_GET_NAME, comm, 0L, 0L, 0L))) | 78 | prog_fd = bpf_program__fd(prog); |
| 112 | goto cleanup_extra; | 79 | if (!ASSERT_GE(prog_fd, 0, "bpf_program__fd")) |
| 113 | CHECK_FAIL(test_task_rename()); | 80 | goto cleanup; |
| 114 | CHECK_FAIL(prctl(PR_SET_NAME, comm, 0L, 0L, 0L)); | 81 | |
| | 82 | err = bpf_prog_test_run_opts(prog_fd, &opts); |
| | 83 | if (!ASSERT_OK(err, "bpf_prog_test_run_opts")) |
| | 84 | goto cleanup; |
| | 85 | |
| | 86 | ASSERT_EQ(opts.retval & 0xffff, 4, "bpf_modify_return_test.result"); |
| | 87 | ASSERT_EQ(opts.retval >> 16, 1, "bpf_modify_return_test.side_effect"); |
| 115 | | 88 | |
| 116 | cleanup_extra: | | |
| 117 | bpf_object__close(obj); | | |
| 118 | cleanup: | 89 | cleanup: |
| 119 | if (i >= MAX_TRAMP_PROGS) | | |
| 120 | i = MAX_TRAMP_PROGS - 1; | | |
| 121 | for (; i >= 0; i--) { | 90 | for (; i >= 0; i--) { |
| 122 | bpf_link__destroy(inst[i].link_fentry); | 91 | bpf_link__destroy(inst[i].link); |
| 123 | bpf_link__destroy(inst[i].link_fexit); | | |
| 124 | bpf_object__close(inst[i].obj); | 92 | bpf_object__close(inst[i].obj); |
| 125 | } | 93 | } |
| 126 | } | 94 | } |