eBPF: In-Kernel Programmability for Networking and Security
It's 2018, and if you're still debugging production issues with strace and tcpdump alone, you're living in the past. The Linux 4.x kernel series has fully embraced eBPF (extended Berkeley Packet Filter), and it's transforming how we think about system observability and networking.
Gone are the days of risky kernel modules that crash your whole box. eBPF gives us a sandboxed, verified runtime inside the kernel. It’s like JavaScript for the kernel, but for real systems engineers.
The Power of kprobes and Tracepoints
The magic of eBPF lies in its ability to attach to almost anything: kprobes (kernel functions), uprobes (userspace functions), or tracepoints. You write a small C program, compile it to eBPF bytecode, and the kernel verifier ensures it won't crash the system before letting it run.
Hands-on: Tracing execve syscalls
Want to see every process being started on your system in real-time? With bcc (BPF Compiler Collection), it's trivial. Here’s a snippet that hooks into the execve system call:
from bcc import BPF
# The eBPF program (C code)
bpf_text = """
#include <uapi/linux/ptrace.h>
int kprobe__sys_execve(struct pt_regs *ctx) {
char comm[16];
bpf_get_current_comm(&comm, sizeof(comm));
bpf_trace_printk("New process started: %s\\n", comm);
return 0;
}
"""
# Load the BPF program
b = BPF(text=bpf_text)
print("Tracing execve... Ctrl-C to stop.")
# Print the output
b.trace_print()
XDP: High-Performance Networking
But eBPF isn't just for tracing. XDP (eXpress Data Path) allows you to run eBPF programs at the earliest possible point in the network stack—directly in the network driver. This is how Cloudflare is mitigating massive DDoS attacks with minimal CPU overhead.
// A simple XDP program to drop all UDP packets
#include <linux/bpf.h>
SEC("prog")
int xdp_drop_udp(struct xdp_md *ctx) {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
// ... logic to parse eth/ip/udp headers ...
// if (protocol == IPPROTO_UDP) return XDP_DROP;
return XDP_PASS;
}
The era of "fixed" kernel functionality is over. We are now in the age of the programmable kernel.