0

GOAL: print Hello every time a system call is executed.

CODE:

_kern.c

#include <linux/bpf.h>
#include "bpf_helpers.h"

SEC("tracepoint/syscalls/sys_enter")
int bpf_sys(struct syscalls_enter_open_args *ctx)
{
        char fmt[] = "Hello\n";
        bpf_trace_printk(fmt, sizeof(fmt));     
        return 0;
}
char _license[] SEC("license") = "GPL";

_user.c

#include <linux/bpf.h>
#include "libbpf.h"
#include <unistd.h>
#include <fcntl.h>

int main(int ac, char **argv)
{
        int prog_fd, fd;
        struct bpf_object *obj;

        if (bpf_prog_load("tracesys_kern.o", BPF_PROG_TYPE_TRACEPOINT,
                          &obj, &prog_fd))
                return 1;

        fd = open("mine_user.c", O_RDONLY);
        close(fd);
        //fork();

        return 0;
}

PROBLEM: when I run the program it just terminates without print "Hello" also if open system call is invoked.

QUESTION: what am I missing? I've tried also sys_enter_open instead of sys_enter

pchaigno
  • 11,313
  • 2
  • 29
  • 54
Maicake
  • 1,046
  • 10
  • 34
  • If you run strace on your program, do you see any failing syscall? – pchaigno Aug 26 '19 at 13:53
  • 2
    You did run `cat /sys/kernel/debug/tracing/trace` or something equivalent to dump the trace, right? The `bpf_trace_printk()` helper does not print to the terminal -- just double-checking you're aware of that. – Qeole Aug 26 '19 at 14:07
  • I've tried also cat /sys/kernel/debug/tracing/trace_pipe but I can't read Hello nowhere. If I use strace the last lines in output are the follow bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_TRACEPOINT, insn_cnt=12, insns=0x55cbad752050, license="GPL", log_level=0, log_size=0, log_buf=0, kern_version=0, prog_flags=0, ...}, 112) = 3 munmap(0x7fb8ef943000, 16781312) = 0 openat(AT_FDCWD, "mine_user.c", O_RDONLY) = 4 close(4) = 0 exit_group(0) = ? +++ exited with 0 +++ – Maicake Aug 26 '19 at 14:36
  • 2
    Looks like your program is loaded, but not attached to the probe. See how `bpf_load.c`, for example, uses libbpf to [load a program](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/samples/bpf/bpf_load.c?h=v5.2#n131) and then [attaches it](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/samples/bpf/bpf_load.c?h=v5.2#n212) to the tracepoint. I think libbpf now also provides [`bpf_program__attach_tracepoint()`](https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/tree/tools/lib/bpf/libbpf.c?h=v5.3-rc1#n4260) as a simpler way to do this. – Qeole Aug 26 '19 at 14:54
  • Thanks! So I should first find the bpf_program with struct *bpf_program prog = bpf_object__find_program_by_title(&obj, "socket") and then call bpf_program__attach_tracepoint(prog, "syscall", "sys_open"). Where I can find the list of tp_category and tp_name that I can use? – Maicake Aug 27 '19 at 08:23
  • 1
    If you have perf installed, you can run `sudo perf list tracepoint` to get the list of tracepoints you can use. – pchaigno Aug 27 '19 at 08:36
  • @Qeole I think you should make your comment into an answer; it might help other users. – pchaigno Aug 27 '19 at 12:06

1 Answers1

2

As for other program types, loading a BPF program takes two steps. First there is the actual load (injecting the program from user space to kernel space, where it passes the verifier), that you performed with bpf_prog_load() in your case. Then, the program is to be attached to one of the BPF hooks, here a tracepoint.

In your sample code, your program is loaded, but not attached to the tracepoint just yet. See how bpf_load.c, for example, uses libbpf to load a program and then attaches it to the tracepoint.

I think recent versions of libbpf now provide bpf_program__attach_tracepoint() as a simpler way to attach the program to the tracepoint.

As pchaigno mentioned, you can list the tracepoints available on your system with sudo perf list tracepoint (you may have to install the perf utility).

Qeole
  • 8,284
  • 1
  • 24
  • 52
  • I've tried to use struct *bpf_program prog = bpf_object__find_program_by_title(obj, "tracepoint/syscalls/sys_enter_open") and then call bpf_program__attach_tracepoint(prog, "syscall", "sys_enter_open") but still the tracing pipe is empty. – Maicake Aug 27 '19 at 13:36
  • In the strace output I see bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_TRACEPOINT, insn_cnt=12, insns=0x55d6f7803050, license="GPL", log_level=0, log_size=0, log_buf=0, kern_version=0, prog_flags=0, ...}, 112) = 3 munmap(0x7f157d73c000, 16781312) = 0 openat(AT_FDCWD, "/sys/kernel/debug/tracing/events/syscalls/sys_enter_open/id", O_RDONLY) = 4 fstat(4, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 read(4, "609\n", 4096) = 4 read(4, "", 4096) = 0 close(4) = 0 – Maicake Aug 27 '19 at 13:39
  • perf_event_open({type=PERF_TYPE_TRACEPOINT, size=PERF_ATTR_SIZE_VER5, config=609, ...}, -1, 0, -1, PERF_FLAG_FD_CLOEXEC) = 4 ioctl(4, PERF_EVENT_IOC_SET_BPF, 0x3) = 0 ioctl(4, PERF_EVENT_IOC_ENABLE, 0) = 0 openat(AT_FDCWD, "mine_user.c", O_RDONLY) = 5 close(5) = 0 exit_group(0) = ? – Maicake Aug 27 '19 at 13:39
  • 1
    Ok I can answer myself this time (at least once XD): open internally calls openat so I have to use sys_enter_openat instead of sys_enter_open........... – Maicake Aug 27 '19 at 14:24