Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Add test ops for BPF_PROG_TYPE_TRACING

The current fexit and fentry tests rely on a different program to
exercise the functions they attach to. Instead of doing this, implement
the test operations for tracing which will also be used for
BPF_MODIFY_RETURN in a subsequent patch.

Also, clean up the fexit test to use the generated skeleton.

Signed-off-by: KP Singh <kpsingh@google.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20200304191853.1529-7-kpsingh@chromium.org

authored by

KP Singh and committed by
Alexei Starovoitov
da00d2f1 aca228cd

+67 -76
+10
include/linux/bpf.h
··· 1156 1156 union bpf_attr __user *uattr); 1157 1157 int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, 1158 1158 union bpf_attr __user *uattr); 1159 + int bpf_prog_test_run_tracing(struct bpf_prog *prog, 1160 + const union bpf_attr *kattr, 1161 + union bpf_attr __user *uattr); 1159 1162 int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, 1160 1163 const union bpf_attr *kattr, 1161 1164 union bpf_attr __user *uattr); ··· 1312 1309 static inline int bpf_prog_test_run_skb(struct bpf_prog *prog, 1313 1310 const union bpf_attr *kattr, 1314 1311 union bpf_attr __user *uattr) 1312 + { 1313 + return -ENOTSUPP; 1314 + } 1315 + 1316 + static inline int bpf_prog_test_run_tracing(struct bpf_prog *prog, 1317 + const union bpf_attr *kattr, 1318 + union bpf_attr __user *uattr) 1315 1319 { 1316 1320 return -ENOTSUPP; 1317 1321 }
+1
kernel/trace/bpf_trace.c
··· 1266 1266 }; 1267 1267 1268 1268 const struct bpf_prog_ops tracing_prog_ops = { 1269 + .test_run = bpf_prog_test_run_tracing, 1269 1270 }; 1270 1271 1271 1272 static bool raw_tp_writable_prog_is_valid_access(int off, int size,
+28 -9
net/bpf/test_run.c
··· 160 160 kfree(data); 161 161 return ERR_PTR(-EFAULT); 162 162 } 163 - if (bpf_fentry_test1(1) != 2 || 164 - bpf_fentry_test2(2, 3) != 5 || 165 - bpf_fentry_test3(4, 5, 6) != 15 || 166 - bpf_fentry_test4((void *)7, 8, 9, 10) != 34 || 167 - bpf_fentry_test5(11, (void *)12, 13, 14, 15) != 65 || 168 - bpf_fentry_test6(16, (void *)17, 18, 19, (void *)20, 21) != 111) { 169 - kfree(data); 170 - return ERR_PTR(-EFAULT); 171 - } 163 + 172 164 return data; 165 + } 166 + 167 + int bpf_prog_test_run_tracing(struct bpf_prog *prog, 168 + const union bpf_attr *kattr, 169 + union bpf_attr __user *uattr) 170 + { 171 + int err = -EFAULT; 172 + 173 + switch (prog->expected_attach_type) { 174 + case BPF_TRACE_FENTRY: 175 + case BPF_TRACE_FEXIT: 176 + if (bpf_fentry_test1(1) != 2 || 177 + bpf_fentry_test2(2, 3) != 5 || 178 + bpf_fentry_test3(4, 5, 6) != 15 || 179 + bpf_fentry_test4((void *)7, 8, 9, 10) != 34 || 180 + bpf_fentry_test5(11, (void *)12, 13, 14, 15) != 65 || 181 + bpf_fentry_test6(16, (void *)17, 18, 19, (void *)20, 21) != 111) 182 + goto out; 183 + break; 184 + default: 185 + goto out; 186 + } 187 + 188 + err = 0; 189 + out: 190 + trace_bpf_test_finish(&err); 191 + return err; 173 192 } 174 193 175 194 static void *bpf_ctx_init(const union bpf_attr *kattr, u32 max_size)
+3 -9
tools/testing/selftests/bpf/prog_tests/fentry_fexit.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2019 Facebook */ 3 3 #include <test_progs.h> 4 - #include "test_pkt_access.skel.h" 5 4 #include "fentry_test.skel.h" 6 5 #include "fexit_test.skel.h" 7 6 8 7 void test_fentry_fexit(void) 9 8 { 10 - struct test_pkt_access *pkt_skel = NULL; 11 9 struct fentry_test *fentry_skel = NULL; 12 10 struct fexit_test *fexit_skel = NULL; 13 11 __u64 *fentry_res, *fexit_res; 14 12 __u32 duration = 0, retval; 15 - int err, pkt_fd, i; 13 + int err, prog_fd, i; 16 14 17 - pkt_skel = test_pkt_access__open_and_load(); 18 - if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n")) 19 - return; 20 15 fentry_skel = fentry_test__open_and_load(); 21 16 if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n")) 22 17 goto close_prog; ··· 26 31 if (CHECK(err, "fexit_attach", "fexit attach failed: %d\n", err)) 27 32 goto close_prog; 28 33 29 - pkt_fd = bpf_program__fd(pkt_skel->progs.test_pkt_access); 30 - err = bpf_prog_test_run(pkt_fd, 1, &pkt_v6, sizeof(pkt_v6), 34 + prog_fd = bpf_program__fd(fexit_skel->progs.test1); 35 + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 31 36 NULL, NULL, &retval, &duration); 32 37 CHECK(err || retval, "ipv6", 33 38 "err %d errno %d retval %d duration %d\n", ··· 44 49 } 45 50 46 51 close_prog: 47 - test_pkt_access__destroy(pkt_skel); 48 52 fentry_test__destroy(fentry_skel); 49 53 fexit_test__destroy(fexit_skel); 50 54 }
+4 -10
tools/testing/selftests/bpf/prog_tests/fentry_test.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2019 Facebook */ 3 3 #include <test_progs.h> 4 - #include "test_pkt_access.skel.h" 5 4 #include "fentry_test.skel.h" 6 5 7 6 void test_fentry_test(void) 8 7 { 9 - struct test_pkt_access *pkt_skel = NULL; 10 8 struct fentry_test *fentry_skel = NULL; 11 - int err, pkt_fd, i; 9 + int err, prog_fd, i; 12 10 __u32 duration = 0, retval; 13 11 __u64 *result; 14 12 15 - pkt_skel = test_pkt_access__open_and_load(); 16 - if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n")) 17 - return; 18 13 fentry_skel = fentry_test__open_and_load(); 19 14 if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n")) 20 15 goto cleanup; ··· 18 23 if (CHECK(err, "fentry_attach", "fentry attach failed: %d\n", err)) 19 24 goto cleanup; 20 25 21 - pkt_fd = bpf_program__fd(pkt_skel->progs.test_pkt_access); 22 - err = bpf_prog_test_run(pkt_fd, 1, &pkt_v6, sizeof(pkt_v6), 26 + prog_fd = bpf_program__fd(fentry_skel->progs.test1); 27 + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 23 28 NULL, NULL, &retval, &duration); 24 - CHECK(err || retval, "ipv6", 29 + CHECK(err || retval, "test_run", 25 30 "err %d errno %d retval %d duration %d\n", 26 31 err, errno, retval, duration); 27 32 ··· 34 39 35 40 cleanup: 36 41 fentry_test__destroy(fentry_skel); 37 - test_pkt_access__destroy(pkt_skel); 38 42 }
+21 -48
tools/testing/selftests/bpf/prog_tests/fexit_test.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2019 Facebook */ 3 3 #include <test_progs.h> 4 + #include "fexit_test.skel.h" 4 5 5 6 void test_fexit_test(void) 6 7 { 7 - struct bpf_prog_load_attr attr = { 8 - .file = "./fexit_test.o", 9 - }; 10 - 11 - char prog_name[] = "fexit/bpf_fentry_testX"; 12 - struct bpf_object *obj = NULL, *pkt_obj; 13 - int err, pkt_fd, kfree_skb_fd, i; 14 - struct bpf_link *link[6] = {}; 15 - struct bpf_program *prog[6]; 8 + struct fexit_test *fexit_skel = NULL; 9 + int err, prog_fd, i; 16 10 __u32 duration = 0, retval; 17 - struct bpf_map *data_map; 18 - const int zero = 0; 19 - u64 result[6]; 11 + __u64 *result; 20 12 21 - err = bpf_prog_load("./test_pkt_access.o", BPF_PROG_TYPE_SCHED_CLS, 22 - &pkt_obj, &pkt_fd); 23 - if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno)) 24 - return; 25 - err = bpf_prog_load_xattr(&attr, &obj, &kfree_skb_fd); 26 - if (CHECK(err, "prog_load fail", "err %d errno %d\n", err, errno)) 27 - goto close_prog; 13 + fexit_skel = fexit_test__open_and_load(); 14 + if (CHECK(!fexit_skel, "fexit_skel_load", "fexit skeleton failed\n")) 15 + goto cleanup; 28 16 29 - for (i = 0; i < 6; i++) { 30 - prog_name[sizeof(prog_name) - 2] = '1' + i; 31 - prog[i] = bpf_object__find_program_by_title(obj, prog_name); 32 - if (CHECK(!prog[i], "find_prog", "prog %s not found\n", prog_name)) 33 - goto close_prog; 34 - link[i] = bpf_program__attach_trace(prog[i]); 35 - if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n")) 36 - goto close_prog; 37 - } 38 - data_map = bpf_object__find_map_by_name(obj, "fexit_te.bss"); 39 - if (CHECK(!data_map, "find_data_map", "data map not found\n")) 40 - goto close_prog; 17 + err = fexit_test__attach(fexit_skel); 18 + if (CHECK(err, "fexit_attach", "fexit attach failed: %d\n", err)) 19 + goto cleanup; 41 20 42 - err = bpf_prog_test_run(pkt_fd, 1, &pkt_v6, sizeof(pkt_v6), 21 + prog_fd = bpf_program__fd(fexit_skel->progs.test1); 22 + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 43 23 NULL, NULL, &retval, &duration); 44 - CHECK(err || retval, "ipv6", 24 + CHECK(err || retval, "test_run", 45 25 "err %d errno %d retval %d duration %d\n", 46 26 err, errno, retval, duration); 47 27 48 - err = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, &result); 49 - if (CHECK(err, "get_result", 50 - "failed to get output data: %d\n", err)) 51 - goto close_prog; 28 + result = (__u64 *)fexit_skel->bss; 29 + for (i = 0; i < 6; i++) { 30 + if (CHECK(result[i] != 1, "result", 31 + "fexit_test%d failed err %lld\n", i + 1, result[i])) 32 + goto cleanup; 33 + } 52 34 53 - for (i = 0; i < 6; i++) 54 - if (CHECK(result[i] != 1, "result", "bpf_fentry_test%d failed err %ld\n", 55 - i + 1, result[i])) 56 - goto close_prog; 57 - 58 - close_prog: 59 - for (i = 0; i < 6; i++) 60 - if (!IS_ERR_OR_NULL(link[i])) 61 - bpf_link__destroy(link[i]); 62 - bpf_object__close(obj); 63 - bpf_object__close(pkt_obj); 35 + cleanup: 36 + fexit_test__destroy(fexit_skel); 64 37 }