Articles

eBPF, Explained: Programmable Superpowers in the Linux Kernel

eBPF runs sandboxed programs inside the Linux kernel without recompiling it. How it works and why it reshaped observability, networking, and security.

Chisato Chisato · · Updated · 5 min read
A CI/CD pipeline of connected stages

eBPF (extended Berkeley Packet Filter) is a Linux kernel technology that runs small, sandboxed programs inside the kernel itself — without modifying kernel source or loading a kernel module. The kernel verifies each program for safety before it runs, then executes it at native speed, attached to hooks in networking, tracing, or security paths.

For most of Linux’s history, adding new kernel behavior meant one of two things: submit a patch to the kernel mailing list and wait years for it to land, or load a kernel module and hope it doesn’t take down the whole system. eBPF is a third path — and it has quietly become one of the most consequential additions to the Linux kernel in recent memory.

What eBPF actually is

An eBPF program is typically written in restricted C (or generated by tools like bpftrace), compiled to eBPF bytecode, and loaded into the kernel, where it attaches to a specific hook — a network path, a syscall, a tracepoint, a function entry or return. From then on it runs every time that hook fires.

The name is historical baggage: the original BPF was a simple filter for packet capture. The extended version, now just called eBPF in most contexts, is a general-purpose in-kernel execution environment that far outgrows that origin.

The in-kernel verifier and JIT compiler

Two components make eBPF both safe and fast.

The verifier runs before any eBPF program executes. It statically analyzes the bytecode to enforce a set of safety guarantees: programs must terminate (no unbounded loops by default), they can’t access arbitrary memory, and all pointer accesses are bounds-checked. If a program fails verification, it never runs — the kernel rejects it at load time. This is fundamentally different from a kernel module, which the kernel trusts unconditionally once loaded.

The JIT compiler then translates verified eBPF bytecode to native machine instructions for the host architecture. The resulting code runs at speeds comparable to compiled kernel code — not interpreted, not emulated.

The practical consequence is that eBPF programs are dynamically loadable, safe by construction, and fast enough for production hot paths.

Why it beats kernel modules

Kernel modules run with full kernel privileges and no memory isolation. A bug in a module — a null dereference, a bad cast — can panic the entire machine. Modules also need to be compiled against the running kernel version, creating a maintenance burden on every kernel upgrade.

eBPF programs are verified before they run, scoped to specific hooks, and can be loaded and unloaded without a reboot or recompile. If you push a broken eBPF program, the verifier rejects it. You don’t lose the machine.

This makes eBPF suitable for production use in ways that kernel module development rarely is.

The three big domains

Observability

eBPF’s original killer app on modern infrastructure is tracing. By attaching to kprobes (arbitrary kernel function entry/exit), uprobes (user-space function entry/exit), and tracepoints (stable kernel instrumentation points), eBPF programs can gather metrics with microsecond resolution — without modifying application code and without the overhead of traditional profiling.

bpftrace is a high-level tracing language that lets you write one-liners to explore kernel behavior. Here’s an illustrative example that counts how many times each process called read():

# bpftrace -e 'tracepoint:syscalls:sys_enter_read { @[comm] = count(); }'

This is illustrative — bpftrace syntax may vary; run man bpftrace on your system.

Tools like Pixie-style continuous profilers use the same mechanism at scale — sampling CPU stacks across all processes, all the time, at low overhead, by running eBPF programs on every node in a cluster. Flame graphs that used to require careful, disruptive profiling sessions can now be generated on-demand from always-on data.

Networking

Network processing is where eBPF’s performance characteristics become most visible. XDP (eXpress Data Path) is an eBPF hook that runs before the kernel’s normal network stack — at the driver layer, on the very first moment a packet arrives. This enables packet filtering, load balancing, and DDoS mitigation at speeds that normal iptables rules can’t approach, because iptables processing happens much later in the networking stack.

Cilium is the most widely deployed eBPF networking tool in the cloud-native space. It replaces kube-proxy and large parts of iptables with eBPF programs that implement Kubernetes network policy, service load balancing, and network visibility natively — with lower latency and linear rather than quadratic scaling as cluster size grows. If you’re running a containerized workload in Kubernetes, there’s a good chance Cilium or a similar eBPF-based CNI is handling your pod networking.

Security

eBPF programs attached to syscall entry/exit points give you a precise view of what every process is doing in real time — which files it opens, which network connections it makes, which binaries it executes. This is the foundation for runtime security tooling.

Falco uses kernel events (and increasingly eBPF programs) to enforce behavioral rules: flag a container that spawns a shell, alert on an unexpected outbound connection, catch privilege escalation attempts. Tetragon takes this further by embedding enforcement directly in the eBPF programs — rather than just alerting, it can drop the suspicious syscall before it completes, blocking an attack in progress rather than logging it after the fact.

This is runtime policy enforcement without agents injected into application containers, without library hooking, and without the performance cost of full system call interception.

How it underpins modern cloud-native infrastructure

eBPF is increasingly infrastructure plumbing rather than a tool you interact with directly. When you install Cilium, deploy a Datadog agent, use Pixie, or enable security monitoring in a managed Kubernetes service, there are eBPF programs running on every node whether you see them or not.

The pattern recurs because the alternative — kernel modules, user-space polling, or library injection — all carry worse tradeoffs. eBPF threads the needle: kernel-level visibility with user-space safety guarantees. It’s also what makes Rust’s rise in systems programming complementary rather than competing — Rust gives you safe low-level code in user space; eBPF gives you safe programmability inside the kernel.

The takeaway

eBPF is not a niche tool for kernel hackers. It is the mechanism behind some of the most widely deployed infrastructure software in cloud computing — the networking, observability, and security layers of systems running at scale. Understanding what it is and what it enables helps you reason about the tools that sit on top of it: why Cilium scales better than kube-proxy, why eBPF-based tracing has low overhead, why runtime security tooling based on eBPF is more reliable than alternatives. The kernel programmability it provides was not possible at this safety level five years ago. It’s now table stakes.

Chisato Chisato · · 4 min read

What Is Secrets Management?

Secrets management stores API keys, passwords, and certificates in a dedicated system instead of config files, with access control, rotation, and audit logs.

#Security #Cloud #DevOps
Chisato Chisato · · 3 min read

What Is a Runbook? Incident Response Playbooks

A runbook is a step-by-step document for handling a specific operational task or incident, turning tribal knowledge into a repeatable procedure.

#DevOps #Cloud #Observability