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?