I have the following simple eBPF program:
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
struct sys_enter_execve_ctx {
unsigned short common_type;
unsigned char common_flags;
unsigned char common_preempt_count;
int common_pid;
int __syscall_nr;
const char *filename;
const char *const * argv;
const char *const * envp;
};
SEC("tp/syscalls/sys_enter_execve")
int handle_execve(struct sys_enter_execve_ctx *ctx) {
bpf_printk("%s\n", ctx->filename);
return 0;
}
char LICENSE[] SEC("license") = "GPL";
and a main program:
#include <stdio.h>
#include "exec.skel.h"
int main(void)
{
struct exec *skel = exec__open();
exec__load(skel);
exec__attach(skel);
getchar();
exec__detach(skel);
exec__destroy(skel);
return 0;
}
and a Makefile
to build everything:
APP=exec
.PHONY: $(APP) vmlinux bpf skel run clean
$(APP): skel
clang exec.c -lbpf -lelf -o $(APP)
vmlinux:
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
bpf: vmlinux
clang -g -O3 -target bpf -D__TARGET_ARCH_x86_64 -c exec.bpf.c -o exec.bpf.o
skel: bpf
bpftool gen skeleton exec.bpf.o name exec > exec.skel.h
run: $(APP)
sudo ./$(APP)
clean:
-rm -rf *.o *.skel.h vmlinux.h $(APP)
When I run make
and make run
everything works fine. In another scenario I wanted to use bpftool
to load and attach the program to a tracepoint. The loading works successfully with:
sudo bpftool prog load ./exec.bpf.o /sys/fs/bpf/exec type tracepoint
sudo bpftool prog list
[...]
44: tracepoint name handle_execve tag 08424f7d1079fa76 gpl
loaded_at 2023-02-26T10:52:47+0100 uid 0
xlated 48B jited 36B memlock 4096B map_ids 11
btf_id 144
From what I understand the loading is independent of the attaching. There are indeed attach
subcommands like bpftool prog attach
, bpftool net attach
etc. but there are not for tracepoints. Also bpftool perf
does not have an attach command:
bpftool perf help
Usage: bpftool perf { show | list }
bpftool perf help }
OPTIONS := { {-j|--json} [{-p|--pretty}] | {-d|--debug} | {-l|--legacy} }
When I trace the libbpf program from the beginning there are bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_TRACEPOINT, ...
, perf_open_event
and bpf(BPF_LINK_CREATE, ...)
system calls to set everything up:
sudo strace -e bpf,perf_event_open,ioctl ./exec
[...]
perf_event_open({type=PERF_TYPE_TRACEPOINT, size=PERF_ATTR_SIZE_VER7, config=733, sample_period=0, sample_type=0, read_format=0, precise_ip=0 /* arbitrary skid */, ...}, -1, 0, -1, PERF_FLAG_FD_CLOEXEC) = 6
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_TRACEPOINT, insn_cnt=2, insns=0x7ffd42bc8550, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(0, 0, 0), prog_flags=0, prog_name="", prog_ifindex=0, expected_attach_type=BPF_CGROUP_INET_INGRESS, prog_btf_fd=0, func_info_rec_size=0, func_info=NULL, func_info_cnt=0, line_info_rec_size=0, line_info=NULL, line_info_cnt=0, attach_btf_id=0, attach_prog_fd=0, fd_array=NULL}, 128) = 7
bpf(BPF_LINK_CREATE, {link_create={prog_fd=7, target_fd=-1, attach_type=BPF_PERF_EVENT, flags=0, perf_event={bpf_cookie=0}}}, 48) = -1 EBADF (Bad file descriptor)
bpf(BPF_LINK_CREATE, {link_create={prog_fd=5, target_fd=6, attach_type=BPF_PERF_EVENT, flags=0, perf_event={bpf_cookie=0}}}, 48) = 7
ioctl(6, PERF_EVENT_IOC_ENABLE, 0) = 0
What am I missing? How can I attach the program to a tracepoint (or kprobe etc.) with bpftool
?