From bc1a85977b950407d67cd1e5b74f261a4bee3284 Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Sat, 16 May 2020 13:06:06 +0900 Subject: samples, bpf: Refactor tail call user progs with libbpf BPF tail call uses the BPF_MAP_TYPE_PROG_ARRAY type map for calling into other BPF programs and this PROG_ARRAY should be filled prior to use. Currently, samples with the PROG_ARRAY type MAP fill this program array with bpf_load. For bpf_load to fill this map, kernel BPF program must specify the section with specific format of / (e.g. SEC("socket/0")) But by using libbpf instead of bpf_load, user program can specify which programs should be added to PROG_ARRAY. The advantage of this approach is that you can selectively add only the programs you want, rather than adding all of them to PROG_ARRAY, and it's much more intuitive than the traditional approach. This commit refactors user programs with the PROG_ARRAY type MAP with libbpf instead of using bpf_load. Signed-off-by: Daniel T. Lee Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Link: https://lore.kernel.org/bpf/20200516040608.1377876-4-danieltimlee@gmail.com --- samples/bpf/tracex5_user.c | 66 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 8 deletions(-) (limited to 'samples/bpf/tracex5_user.c') diff --git a/samples/bpf/tracex5_user.c b/samples/bpf/tracex5_user.c index c2317b39e0d2..98dad57a96c4 100644 --- a/samples/bpf/tracex5_user.c +++ b/samples/bpf/tracex5_user.c @@ -1,15 +1,21 @@ // SPDX-License-Identifier: GPL-2.0 #include -#include +#include #include #include #include #include #include -#include "bpf_load.h" +#include #include #include "trace_helpers.h" +#ifdef __mips__ +#define MAX_ENTRIES 6000 /* MIPS n64 syscalls start at 5000 */ +#else +#define MAX_ENTRIES 1024 +#endif + /* install fake seccomp program to enable seccomp code path inside the kernel, * so that our kprobe attached to seccomp_phase1() can be triggered */ @@ -28,16 +34,57 @@ static void install_accept_all_seccomp(void) int main(int ac, char **argv) { - FILE *f; - char filename[256]; struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; + struct bpf_link *link = NULL; + struct bpf_program *prog; + struct bpf_object *obj; + int key, fd, progs_fd; + char filename[256]; + const char *title; + FILE *f; - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); setrlimit(RLIMIT_MEMLOCK, &r); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); - return 1; + snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + obj = bpf_object__open_file(filename, NULL); + if (libbpf_get_error(obj)) { + fprintf(stderr, "ERROR: opening BPF object file failed\n"); + return 0; + } + + prog = bpf_object__find_program_by_name(obj, "bpf_prog1"); + if (!prog) { + printf("finding a prog in obj file failed\n"); + goto cleanup; + } + + /* load BPF program */ + if (bpf_object__load(obj)) { + fprintf(stderr, "ERROR: loading BPF object file failed\n"); + goto cleanup; + } + + link = bpf_program__attach(prog); + if (libbpf_get_error(link)) { + fprintf(stderr, "ERROR: bpf_program__attach failed\n"); + link = NULL; + goto cleanup; + } + + progs_fd = bpf_object__find_map_fd_by_name(obj, "progs"); + if (progs_fd < 0) { + fprintf(stderr, "ERROR: finding a map in obj file failed\n"); + goto cleanup; + } + + bpf_object__for_each_program(prog, obj) { + title = bpf_program__title(prog, false); + /* register only syscalls to PROG_ARRAY */ + if (sscanf(title, "kprobe/%d", &key) != 1) + continue; + + fd = bpf_program__fd(prog); + bpf_map_update_elem(progs_fd, &key, &fd, BPF_ANY); } install_accept_all_seccomp(); @@ -47,5 +94,8 @@ int main(int ac, char **argv) read_trace_pipe(); +cleanup: + bpf_link__destroy(link); + bpf_object__close(obj); return 0; } -- cgit v1.2.3-59-g8ed1b