cd ../lexicon
sys/docs/lexicon/ebpf-extended-berkeley-packet-filter-3.md
Lexicon Entry

eBPF (Extended Berkeley Packet Filter)

eBPF is a kernel technology that allows sandboxed, event-driven programs to be loaded and executed inside the Linux kernel at runtime without modifying kernel source or loading kernel modules. It matters because it exposes near-zero-overhead observability, networking, and security hooks directly at the syscall, network, and hardware trace-point layer, eliminating the need for kernel patches or costly context-switching to userspace.

At its core, eBPF is a restricted, register-based virtual machine embedded in the Linux kernel. Programs are written in a subset of C, compiled to eBPF bytecode via LLVM/Clang, and loaded via the bpf() syscall. Before execution, the bytecode is passed through the in-kernel verifier, a static analysis engine that walks every possible execution path to guarantee the program terminates, never accesses out-of-bounds memory, and holds no unbounded loops (bounded loops are permitted since kernel 5.3 via the verifier’s loop-detection). Programs that pass verification are then translated by a JIT compiler into native machine code, so execution cost approaches that of a compiled kernel module rather than an interpreted script.

Programs attach to specific hook points, and the hook type determines both the program type (BPF_PROG_TYPE_*) and the set of kernel helper functions it may call. Common attach points include kprobes/uprobes (dynamic tracing of kernel/user functions), tracepoints, XDP (eXpress Data Path, operating at the NIC driver level before sk_buff allocation), TC (traffic control ingress/egress), cgroup hooks, and LSM hooks for security enforcement. Data is exchanged between kernel-space programs and userspace consumers through eBPF maps — key/value structures such as HASH, ARRAY, LRU_HASH, PERCPU variants, and the modern BPF_MAP_TYPE_RINGBUF, which superseded the older perf buffer for lower-overhead, lock-free event streaming to userspace.

  • CO-RE (Compile Once – Run Everywhere): Uses BTF (BPF Type Format) metadata to resolve struct offset relocations at load time, decoupling compiled programs from a specific kernel’s memory layout — critical for portability across heterogeneous fleet kernel versions.
  • Tail calls: Allow one eBPF program to jump into another (via bpf_tail_call) without growing the call stack, used to work around the historically limited instruction-count and complexity budget enforced by the verifier.
  • Verifier complexity limits: Each program is capped by a processed-instruction ceiling (historically 1M, tunable in newer kernels via bpf_jit_limit and complexity heuristics), forcing careful program decomposition for anything beyond trivial logic.
  • Safe memory access: Reads from arbitrary kernel/user memory require bpf_probe_read_kernel/bpf_probe_read_user rather than raw pointer dereference, since the verifier cannot statically prove the validity of arbitrary addresses.

Architecturally, eBPF underpins sidecar-less service mesh data planes (Cilium, Isovalent), kernel-level runtime security enforcement (Falco, Tetragon), and low-overhead continuous profiling (Parca, Pixie) by replacing packet-copying userspace agents with in-kernel filtering and aggregation, cutting per-packet or per-syscall overhead dramatically. The trade-off is operational: debugging verifier rejections requires reading raw bytecode dumps, kernel version skew still breaks non-CO-RE programs in mixed-fleet environments, and privileged CAP_BPF/CAP_SYS_ADMIN requirements mean eBPF-based tooling itself becomes part of the security attack surface that must be audited alongside the workloads it observes.