History

selftests/bpf: Add missing trampoline program type to trampoline_count test

Currently the trampoline_count test doesn't include any fmod_ret bpf programs, fix it to make the test cover all possible trampoline program types. Since fmod_ret bpf programs can't be attached to __set_task_comm function, as it's neither whitelisted for error injection nor a security hook, change it to bpf_modify_return_test. This patch also does some other cleanups such as removing duplicate code, dropping inconsistent comments, etc.

Yuntao Wang committed 4 years ago

Commit b23316a1 parent 96af42c3 files · +61 −91Browse files

Unified · Split

3 files
  1. include/linux/bpf.h +1 −1
  2. tools/testing/selftests/bpf/prog_tests/trampoline_count.c +51 −83
  3. tools/testing/selftests/bpf/progs/test_trampoline_count.c +9 −7
include/linux/bpf.h+1−1
@@ -724,7 +724,7 @@ struct btf_func_model { · 723 unmodified lines
724#define BPF_TRAMP_F_RET_FENTRY_RET BIT(4)724#define BPF_TRAMP_F_RET_FENTRY_RET BIT(4)
725 725
726/* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50726/* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50
727 * bytes on x86. Pick a number to fit into BPF_IMAGE_SIZE / 2727 * bytes on x86.
728 */728 */
729#define BPF_MAX_TRAMP_LINKS 38729#define BPF_MAX_TRAMP_LINKS 38
730 730
tools/testing/selftests/bpf/prog_tests/trampoline_count.c+51−83
@@ -1,126 +1,94 @@
1// SPDX-License-Identifier: GPL-2.0-only1// SPDX-License-Identifier: GPL-2.0-only
2#define _GNU_SOURCE2#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 385#define MAX_TRAMP_PROGS 38
8 6
9struct inst {7struct 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
15static int test_task_rename(void)12static 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
33static 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 */
45void serial_test_trampoline_count(void)36void 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
116cleanup_extra:
117 bpf_object__close(obj);
118cleanup:89cleanup:
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}
tools/testing/selftests/bpf/progs/test_trampoline_count.c+9−7
@@ -1,20 +1,22 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2#include <stdbool.h>
3#include <stddef.h>
4#include <linux/bpf.h>2#include <linux/bpf.h>
5#include <bpf/bpf_helpers.h>3#include <bpf/bpf_helpers.h>
6#include <bpf/bpf_tracing.h>4#include <bpf/bpf_tracing.h>
7 5
8struct task_struct;6SEC("fentry/bpf_modify_return_test")
7int BPF_PROG(fentry_test, int a, int *b)
8{
9 return 0;
10}
9 11
10SEC("fentry/__set_task_comm")12SEC("fmod_ret/bpf_modify_return_test")
11int BPF_PROG(prog1, struct task_struct *tsk, const char *buf, bool exec)13int BPF_PROG(fmod_ret_test, int a, int *b, int ret)
12{14{
13 return 0;15 return 0;
14}16}
15 17
16SEC("fexit/__set_task_comm")18SEC("fexit/bpf_modify_return_test")
17int BPF_PROG(prog2, struct task_struct *tsk, const char *buf, bool exec)19int BPF_PROG(fexit_test, int a, int *b, int ret)
18{20{
19 return 0;21 return 0;
20}22}