如何通过kprobe挂载BPF程序到内核函数?类ip/tc方式挂载到内核/用户态函数
Great questions! Let’s break this down clearly, with practical examples you can try right away.
kprobe is the standard way to dynamically trace kernel functions without modifying core kernel code. Here's a hands-on workflow:
Step 1: Write your BPF kprobe program
Create a C file (e.g., kprobe_execve.c) with your tracing logic:
#include <vmlinux.h> #include <bpf/bpf_helpers.h> // Attach to the sys_execve kernel function entry point SEC("kprobe/sys_execve") int BPF_KPROBE(sys_execve, const char __user *filename) { char comm[16]; // Fetch the current process name bpf_get_current_comm(&comm, sizeof(comm)); // Log to the kernel trace buffer (view with `cat /sys/kernel/debug/tracing/trace_pipe`) bpf_printk("Process %s is executing: %s\n", comm, filename); return 0; } // Required license for kernel compatibility char _license[] SEC("license") = "GPL";
Step 2: Compile the BPF program
Use Clang to cross-compile for the BPF target:
clang -target bpf -D__TARGET_ARCH_x86_64 -I/usr/src/linux-headers-$(uname -r)/ -O2 -c kprobe_execve.c -o kprobe_execve.o
(Adjust the header path if your kernel headers are stored elsewhere)
Step 3: Attach the program with bpftool
bpftool is the official command-line tool for managing BPF objects, and it’s how you’ll hook the kprobe to the kernel function:
# Load the compiled BPF program into the kernel bpftool prog load kprobe_execve.o /sys/fs/bpf/kprobe_execve # Attach it to the sys_execve kernel function bpftool link attach kprobe name sys_execve prog /sys/fs/bpf/kprobe_execve
Or combine it into a single concise command:
bpftool prog load kprobe_execve.o /sys/fs/bpf/kprobe_execve type kprobe attach name sys_execve
To trace function returns (kretprobe), modify the program to use BPF_KRETPROBE and set the section to SEC("kretprobe/sys_execve"), then attach with type kretprobe instead.
ip/tc The ip and tc tools are purpose-built for network stack BPF integration, but there’s no direct equivalent for generic kernel/user-space tracing—instead, bpftool (and bpftrace for quick one-liners) fills this role with similar command-line simplicity.
For Kernel Functions (kprobe/kretprobe)
As shown in the first question, bpftool acts as the counterpart to ip/tc for kernel function tracing. Its commands follow a pattern similar to how you’d attach XDP or clsact programs, making it easy to use for quick setup.
For User-Space Functions (uprobe/uretprobe)
To trace user-space functions, use uprobe (for entry) or uretprobe (for return). Here’s how to do it with bpftool:
Step 1: Write the uprobe program
Create uprobe_readline.c to trace the readline function in /bin/bash:
#include <bpf/bpf_helpers.h> SEC("uprobe/readline") int BPF_UPROBE(readline) { char comm[16]; bpf_get_current_comm(&comm, sizeof(comm)); bpf_printk("Process %s called readline()\n", comm); return 0; } char _license[] SEC("license") = "GPL";
Step 2: Compile and attach
# Compile the program clang -target bpf -D__TARGET_ARCH_x86_64 -O2 -c uprobe_readline.c -o uprobe_readline.o # Attach to a specific bash process (replace 1234 with your target PID) bpftool prog load uprobe_readline.o /sys/fs/bpf/uprobe_readline type uprobe attach pid 1234 /bin/bash:readline # Or attach to all running bash processes bpftool prog load uprobe_readline.o /sys/fs/bpf/uprobe_readline type uprobe attach name bash /bin/bash:readline
Quick one-liners with bpftrace
If you don’t want to write a full C program, bpftrace lets you trace functions with single command-line statements—just like how you’d use ip/tc for quick network BPF setup:
# Trace kernel sys_execve calls in real time bpftrace -e 'kprobe:sys_execve { printf("%s is executing: %s\n", comm, str(arg0)); }' # Trace user-space readline calls in all bash processes bpftrace -e 'uprobe:/bin/bash:readline { printf("%s called readline\n", comm); }'
内容的提问来源于stack exchange,提问作者dippynark

