Skip to main content
  1. Posts/

eBPF for Linux Admins: Part VIII

·3 mins· loading · loading ·
Ansil H
ebpf kprobes
Author
Ansil H
DevOps Guy
eBPF - This article is part of a series.
Part 8: This Article

In the last chapter, we used kprobes to trace a kernel function. But we used that in a kernel module.

In this chapter, we are going to trigger an eBPF program when kernel executes do_sys_openat2.

For loading modules, there are user space commands (insmod,rmmod, modprobe and modinfo).

But what we have for loading eBPF program to handle kprobes ?

There are two options;

  1. Write our own eBPF loader program.
  2. Use an eBPF utility called bpftool

Let’s take the second option for now and we will use the other option in a future series 😉

So let’s install the bpftool first.

sudo apt-get install linux-tools-$(uname -r)

The goal here is same as the previous one ; write an eBPF program that prints the files opened by a process.

  • Create a scratch area.
mkdir -p ebpf-tutor/kprobe_example01
cd !$
  • Below command is needed for generating arch specific types of running kernel and don’t miss it 😃
bpftool btf dump file /sys/kernel/btf/vmlinux format c >vmlinux.h
  • Create the program.
vi ebpf_kprobe_openat.c
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <string.h>

#define TARGET_NAME "sample_write"

SEC("kprobe/do_sys_openat2")
int kprobe__do_sys_openat2(struct pt_regs *ctx) {
    char filename[256];
    char comm[TASK_COMM_LEN] = {};
    const char fmt_str[] = "do_sys_openat2 called by:%s file:%s pid:%d";
    u32 pid = bpf_get_current_pid_tgid() ;  // Get current process PID

    // Read the filename from the second argument
    // The x86 arch/ABI have first argument in di and second in si registers (man syscall) 
    bpf_probe_read(&filename, sizeof(filename), (char *)ctx->si);

    // Read the current process name
    bpf_get_current_comm(&comm, sizeof(comm));

    // Compare process name with our "sample_write" name
    if (strcmp(comm, TARGET_NAME) == 0) {
        // Print a message with filename, process name, and PID
	bpf_trace_printk(fmt_str,sizeof(fmt_str),comm,filename,pid);
	return 0;
    }

    return 0;
}
char _license[] SEC("license") = "GPL";
  • Compile it
clang -O2 -g -Wall -target bpf -c ebpf_kprobe_openat.c -o ebpf_kprobe_openat.o 
  • Load and attach the program to the function. (Somewhat similar to loading module using insmod, but not exactly )
sudo bpftool prog load  ebpf_kprobe_openat.o /sys/fs/bpf/ebpf_kprobe_openat type kprobe autoattach
  • Execute below command on a separate session. (Somewhat similar to dmesg, but not exactly 😃 )
sudo cat /sys/kernel/debug/tracing/trace_pipe
  • Now execute the sample_write file.

The output of the other terminal where we are running cat will show the details we were looking for.

    sample_write-970     [003] ...21  1223.400317: bpf_trace_printk: do_sys_openat2 called by:sample_write file:/etc/ld.so.cache pid:970
    sample_write-970     [003] ...21  1223.400578: bpf_trace_printk: do_sys_openat2 called by:sample_write file:/lib/x86_64-linux-gnu/libc.so.6 pid:970
    sample_write-970     [003] ...21  1223.401672: bpf_trace_printk: do_sys_openat2 called by:sample_write file:./sample.txt pid:970

You can unload/unregister the eBPF program using below command. (Somewhat similar to rmmod, but not exactly 😃 😃 )

sudo rm /sys/fs/bpf/ebpf_kprobe_openat

We are getting closer to the wonderful world of eBPF ,but without eBPF maps, we can’t conclude this series. In the next and final chapter, we will discuss eBPF maps and how user space programs can interact with eBPF and vice versa. Stay tuned.!!

eBPF - This article is part of a series.
Part 8: This Article

Related

eBPF for Linux Admins: Part VII
·6 mins· loading · loading
Ansil H
ebpf kernel kprobes
eBPF for Linux Admins: Part VI
·4 mins· loading · loading
Ansil H
ebpf kernel kprobes
eBPF for Linux Admins: Part V
·3 mins· loading · loading
Ansil H
ebpf