eBPF
In one line
Section titled “In one line”eBPF lets you load a small sandboxed program into the running Linux kernel and attach it to a hook (a syscall, a kernel function, a network device, a security check). The kernel proves the program is memory-safe and will terminate before it runs it. No kernel module, no reboot.
Why it exists
Section titled “Why it exists”- 1992: BPF. Steven McCanne and Van Jacobson wrote “The BSD Packet Filter” (published at USENIX in January 1993). Copying every packet to user space for
tcpdumpwas slow, so they put a tiny register-based virtual machine in the kernel. User space hands it a filter program, and the kernel copies out only the packets that match. This is still what runs when you typetcpdump port 443, and what seccomp filters use. - The gap. Anything else that needed logic inside the kernel had two options: get a patch merged upstream and wait years for distributions to ship it, or write a kernel module. A module is unrestricted native code: one bad pointer panics the machine, and it must be rebuilt for every kernel version.
- 2014: eBPF. Alexei Starovoitov extended the virtual machine: 64-bit registers, more of them, function calls, maps for state, and a verifier. Linux 3.18 (December 2014) added the
bpf()system call. Programs could then attach to kprobes, tracepoints and sockets, and to the network driver receive path with XDP (eXpress Data Path, Linux 4.8, 2016). - Now. eBPF is a general in-kernel runtime. Networking (Cilium, Katran), observability (bpftrace, Pixie, Parca), security (Falco, Tetragon), and since Linux 6.12 even CPU schedulers (sched_ext) are written as eBPF programs. The original BPF is now called classic BPF (cBPF).
How it works
Section titled “How it works”- Write. The kernel-side program is restricted C or Rust: no unbounded loops, no arbitrary function calls, a 512-byte stack. A user-space agent (Go, Rust, C, Python) loads it and reads its results.
- Compile.
clang -target bpfproduces an ELF object with BPF bytecode, map definitions and BTF (BPF Type Format, compact type information about the program). - Relocate (CO-RE). Kernel structs change between versions. With CO-RE (Compile Once, Run Everywhere) the object records which struct fields it reads. At load time the loader library (libbpf, cilium/ebpf, Aya) compares that with the running kernel’s BTF in
/sys/kernel/btf/vmlinuxand patches the field offsets. One binary runs on many kernels, with no compiler or kernel headers on the host. The older approach, used by bcc, compiled C on every host at start-up. - Load. The loader calls
bpf(BPF_MAP_CREATE)for each map andbpf(BPF_PROG_LOAD)with the bytecode and a program type. The kernel checks capabilities first (see the control section below). - Verify. The verifier walks every possible execution path and tracks the type and value range of every register and stack slot. It rejects the program unless it can prove that:
- every memory access is inside a known object (stack, map value, packet bounds, a BTF-typed kernel struct);
- every pointer that may be NULL is checked before use;
- the program terminates: loops must have a provable bound (allowed since Linux 5.3), and the whole analysis must finish within 1 million processed instructions;
- it calls only the helpers and kfuncs allowed for its program type;
- it leaks no kernel pointers to places an unprivileged user could read.
- JIT. The in-kernel JIT compiler translates the bytecode to native machine instructions, so the program runs at close to the speed of compiled kernel code.
- Attach. The loader attaches the program to a hook. Modern attachments return a link, a kernel object held by a file descriptor. When the last reference closes, the program detaches. To keep a program after the loader exits, pin the link or program as a file under
/sys/fs/bpf(the BPF file system, bpffs). - Run. Each time the hook fires, the program runs to completion in kernel context with a context argument (a packet, the probed function’s arguments, a syscall record). Its return value means something specific to the hook: drop or pass a packet, allow or deny an operation.
- Keep state in maps. Maps are kernel key-value stores shared between programs and user space: hash, array, per-CPU variants, LRU hash, LPM trie (longest prefix match, for CIDR lookups), program arrays for tail calls. User space reads and writes them through the
bpf()syscall. - Send events to user space. The ring buffer map (
BPF_MAP_TYPE_RINGBUF, Linux 5.8) is one buffer shared across CPUs that keeps event order. The older perf buffer is one buffer per CPU. The agent polls withepoll. - Call into the kernel. A program cannot call arbitrary kernel functions. It may call helpers (a fixed, stable list such as
bpf_map_lookup_elem,bpf_ktime_get_ns,bpf_probe_read_kernel) and kfuncs (kernel functions explicitly exported to BPF, not a stable interface).
Hook types
Section titled “Hook types”| Hook | Where it runs | What it can see and do | Typical tool |
|---|---|---|---|
| kprobe, kretprobe | entry or return of almost any kernel function | read arguments and kernel memory; no stable interface, function names change between kernels | bpftrace, bcc, Tetragon |
| fentry, fexit | same places, through a BPF trampoline (Linux 5.5), needs BTF | typed arguments, lower overhead than kprobes; fmod_ret can replace the return value of functions that allow it |
newer libbpf tools, Cilium |
| tracepoint, raw tracepoint | fixed points the kernel developers placed (sched:sched_switch, syscalls:sys_enter_openat) |
stable argument layout; read only | Falco, bpftrace |
| uprobe, uretprobe, USDT | a function or marker in a user-space binary or library | read arguments and user memory, for example plaintext before SSL_write encrypts it |
Pixie, bpftrace |
| perf event | a timer or hardware counter, for example 99 times per second per CPU | capture kernel and user stack traces | Parca, Pyroscope |
| XDP | network driver receive path, before the kernel allocates a socket buffer | drop, pass, rewrite, bounce back or redirect a packet (XDP_DROP, XDP_PASS, XDP_TX, XDP_REDIRECT) |
Katran, Cilium, DDoS filters |
| tc (traffic control) | ingress and egress of a network device, on socket buffers | full packet access and rewrite, redirect between devices, both directions | Cilium datapath |
| cgroup | socket and network events for every process in a cgroup: connect, bind, sendmsg, socket options, device access |
allow, deny or rewrite, for example translate a Service IP to a backend at connect() time |
Cilium kube-proxy replacement, container runtimes for the device allowlist |
| socket filter, sockmap | a socket, or a set of sockets | filter packets on a socket; splice data between sockets without leaving the kernel | tcpdump (classic BPF), service mesh acceleration |
| LSM | Linux Security Module hooks such as file_open, bprm_check_security, socket_connect (Linux 5.7) |
return an error to deny the operation | Tetragon, systemd filesystem restrictions |
| struct_ops | a kernel operations table implemented in BPF | supply TCP congestion control or a CPU scheduler (sched_ext, Linux 6.12) | scx schedulers |
Tools and what they use eBPF for
Section titled “Tools and what they use eBPF for”| Tool | Uses eBPF for | Hooks |
|---|---|---|
| Cilium | Kubernetes pod networking (CNI), Service load balancing without kube-proxy, network policy, transparent encryption, flow visibility (Hubble) | tc, XDP, cgroup socket hooks |
| Tetragon | runtime security: process, file and network events filtered in the kernel, and enforcement by sending a signal or overriding a return value | kprobes, tracepoints, LSM |
| Falco | threat detection: streams syscall events to a user-space rule engine. The modern eBPF probe is the default driver; a kernel module is the alternative | tracepoints |
| Pixie | Kubernetes observability without code changes: captures HTTP, gRPC and SQL traffic and CPU profiles | kprobes, uprobes, perf events |
| Parca, Pyroscope | continuous CPU profiling of the whole node by sampling stack traces | perf events |
| bpftrace | one-line and scripted tracing in an awk-like language | kprobes, uprobes, tracepoints, USDT, fentry |
| bcc | toolkit and library of ready tracing tools (execsnoop, opensnoop, biolatency); the classic tools compile C on the host, the libbpf-tools ports use CO-RE |
kprobes, tracepoints, uprobes |
| Katran | layer 4 load balancer from Meta: picks a backend and encapsulates the packet in the driver | XDP |
| Inspektor Gadget | runs tracing “gadgets” packaged as OCI images and tags their events with pod and container names | kprobes, tracepoints, tc |
For Cilium’s use as a service mesh data plane, see mTLS and service mesh.
Controlling what eBPF can do
Section titled “Controlling what eBPF can do”An eBPF agent with tracing privileges sees every syscall argument, every packet and, through uprobes, plaintext before TLS encrypts it. Treat the right to load eBPF as equal to root on the node.
1. Who may load
Section titled “1. Who may load”Capability (all since Linux 5.8, except CAP_SYS_ADMIN) |
Allows |
|---|---|
CAP_BPF |
create maps, load programs, use most bpf() commands |
CAP_BPF + CAP_PERFMON |
load tracing programs (kprobe, tracepoint, fentry, perf event), read kernel memory |
CAP_BPF + CAP_NET_ADMIN |
load and attach networking programs (XDP, tc, cgroup socket hooks) |
CAP_SYS_ADMIN |
everything above, plus the few operations still reserved for it. Before 5.8 this was the only option |
| none | only if unprivileged_bpf_disabled is 0: socket filter and cgroup skb programs, at most 4096 instructions, extra verifier restrictions |
The sysctl kernel.unprivileged_bpf_disabled:
| Value | Meaning |
|---|---|
0 |
unprivileged bpf() calls are allowed |
1 |
disabled; cannot be changed back until reboot |
2 |
disabled; an administrator can still change it to 0 or 1 |
The default is 2 when the kernel is built with CONFIG_BPF_UNPRIV_DEFAULT_OFF, which itself defaults to yes. Set it to 1 on production nodes. Capability checks still apply at every value.
These capabilities are checked in the initial user namespace. Root inside a user-namespaced container does not get them.
2. What the verifier guarantees, and what it does not
Section titled “2. What the verifier guarantees, and what it does not”Guarantees: the program cannot crash the kernel, cannot read or write memory outside objects it was given, cannot loop forever, and calls only what its type permits.
Does not guarantee: that the program is harmless. The verifier checks safety, not intent. A valid program may still:
- read every syscall argument, file path, command line and environment, and read arbitrary kernel memory with
bpf_probe_read_kernel(tracing types); - read user memory of any process, including keys and plaintext, with
bpf_probe_read_userand uprobes; - send all of it anywhere through its user-space agent;
- write user memory of the current task with
bpf_probe_write_user. The kernel logs a warning with the PID and process name whenever a program that uses it is attached; - make a kernel function fail with
bpf_override_return. This needsCONFIG_BPF_KPROBE_OVERRIDEand works only on functions taggedALLOW_ERROR_INJECTION, which includes syscall entry points; - kill processes with
bpf_send_signal; - drop, redirect or rewrite packets (XDP, tc), and deny operations (LSM).
The same helpers that make Tetragon able to enforce policy make an eBPF rootkit able to hide files, hide itself from ps, and fake syscall results.
3. Kernel lockdown
Section titled “3. Kernel lockdown”The lockdown LSM (Linux 5.4) limits what even root can do to the running kernel. It has two modes, and each blocks more BPF.
| Mode | Blocks for BPF and tracing | Effect |
|---|---|---|
| none | nothing | default without Secure Boot policy |
| integrity | bpf_probe_write_user; also unsigned modules, /dev/mem, kexec of unsigned images, debugfs |
observability tools keep working; programs cannot modify user memory |
| confidentiality | everything in integrity, plus BPF reads of kernel memory (bpf_probe_read_kernel), kprobes, perf and tracefs |
most eBPF tracing and profiling stops working |
Check with cat /sys/kernel/security/lockdown; the active mode is in brackets. Several distributions switch to integrity mode when UEFI Secure Boot is on.
4. Signed programs
Section titled “4. Signed programs”Linux 6.18 added signature verification to BPF_PROG_LOAD: the caller passes a signature and a keyring ID, and the kernel refuses the program if the signature does not verify. The design signs a small loader program. The loader carries the hash of the real program and maps and checks it before it loads them, because CO-RE relocation changes the final instructions on each host.
Two limits, as of mid 2026:
- A signature is optional. An unsigned program loads as before unless a security policy refuses it, and that policy layer (through LSM hooks) was still being developed on the mailing lists in 2026.
- libbpf’s loader generation becomes part of the trusted base.
Until policy enforcement lands in the kernels you run, enforce provenance one level up: sign the agent’s container image and verify it at admission.
5. BPF tokens
Section titled “5. BPF tokens”CAP_BPF cannot be granted inside a user namespace, so a rootless or user-namespaced container could not use eBPF at all. BPF tokens (Linux 6.9) fix that by delegation. A privileged process such as the container runtime mounts a bpffs instance for the container with options that list what is allowed: delegate_cmds (which bpf() commands), delegate_maps (map types), delegate_progs (program types), delegate_attachs (attach types). The workload creates a token from that mount with BPF_TOKEN_CREATE and passes it with each bpf() call. The token works only inside the user namespace that owns the mount. LSMs can inspect token creation and use.
This is the way to give one workload “XDP programs and hash maps, nothing else” in place of node-wide CAP_BPF.
6. BPF LSM and other LSM policy
Section titled “6. BPF LSM and other LSM policy”- BPF LSM (Linux 5.7,
CONFIG_BPF_LSM, andbpfin the kernel’s active LSM list) attaches eBPF programs to LSM hooks. There are hooks on thebpf()syscall itself, so a small trusted program can decide which processes may load programs or create maps. - SELinux has a
bpfobject class with separate permissions for creating maps and loading programs, so policy can limitbpf()to named domains.
7. seccomp
Section titled “7. seccomp”A workload that has no reason to call bpf() should not be able to. Docker’s default seccomp profile denies the bpf syscall unless the container has CAP_SYS_ADMIN. In Kubernetes, seccompProfile.type: RuntimeDefault applies the runtime’s default profile. This matters because a capability check is a single line of defence, and verifier bugs have been exploitable by anyone who could reach the syscall.
8. Kubernetes controls
Section titled “8. Kubernetes controls”- Pod Security Standards. Enforce
restricted(or at leastbaseline) on every application namespace. Baseline forbids privileged containers, host namespaces (hostPID,hostNetwork,hostIPC), hostPath volumes and capabilities outside a short list that has noBPF,PERFMON,NET_ADMINorSYS_ADMIN. Restricted also requires droppingALLcapabilities and setting a seccomp profile. - Put eBPF agents in their own namespaces with the
privilegedlevel, and nothing else there. - Allowlist by admission policy. A ValidatingAdmissionPolicy, Kyverno or Gatekeeper rule that rejects any pod with
privileged: true,hostPID, or addedBPF,PERFMON,SYS_ADMINorNET_ADMIN, unless namespace, service account and image match a named list (the CNI, the runtime security agent, the profiler). - Prefer narrow capabilities over
privileged. Many agents run withBPF,PERFMON,NET_ADMINand a few more, plus specific hostPath mounts (/sys/fs/bpf,/sys/kernel/btf).privileged: truealso removes seccomp and device restrictions. - Sign and pin the agent images. Verify signatures at admission and reference images by digest. The image is the real trust boundary for what gets loaded.
- Limit who can create DaemonSets and who can
execinto agent pods. Either is node root on every node.
9. Auditing what is loaded
Section titled “9. Auditing what is loaded”bpftool prog show # every loaded program: id, type, name, load time, uid, map idsbpftool prog show --json | jq '.[] | {id, type, name, pids}'bpftool map show # every map: id, type, name, key/value size, max entries, memlockbpftool link show # attachments that are held by linksbpftool perf show # kprobes, uprobes and tracepoints, with the owning PIDbpftool net show # XDP and tc programs per interfacebpftool cgroup tree # programs attached to cgroupsbpftool prog dump xlated id 42 # the verified instructions of one programfind /sys/fs/bpf -maxdepth 3 # pinned objects that outlive their loaderOutput shape:
42: kprobe name trace_execve tag 3b185187f1855c4c gpl loaded_at 2026-11-12T09:14:03+0000 uid 0 xlated 528B jited 301B memlock 4096B map_ids 7,8 pids agent(1830)- Audit log. The kernel writes a record of type
BPF(1334) withprog-id=N op=LOADorop=UNLOADfor every program load and unload when audit is on. Add a syscall rule to see who called it:auditctl -a always,exit -F arch=b64 -S bpf -k bpf. - Kernel log.
dmesg | grep bpf_probe_write_usershows any program that attached with the user-memory write helper. - Runtime statistics.
sysctl kernel.bpf_stats_enabled=1makes the kernel count run time and run count per program (default 0, small overhead).bpftool prog showthen printsrun_time_nsandrun_cnt. - Baseline and diff. Record the expected set of program names, types and owning processes per node role. Alert on a program whose loader is not a known agent, on tracing or LSM programs that appear outside a rollout, and on new pins in
/sys/fs/bpf. - Limit of this. An attacker with the same privileges can hook the syscalls
bpftooluses and hide entries. Ship audit records off the node, and rely on prevention (the controls above) more than on detection.
10. Resource and performance limits
Section titled “10. Resource and performance limits”| Limit | Value | Notes |
|---|---|---|
| Verifier budget | 1 million processed instructions per program | counts instructions the verifier analyses across all paths, not program size; large programs are split with tail calls |
Program size without CAP_BPF |
4096 instructions | |
| Stack | 512 bytes per program | larger data goes in maps |
| Tail calls | 33 in a chain | |
| Map memory | charged to the memory cgroup of the creating process since Linux 5.11 | before 5.11 it was charged to RLIMIT_MEMLOCK. A map sized for millions of entries can push an agent pod into its memory limit |
Overhead comes from how often the hook fires, not from the program alone. A kprobe on a function called millions of times per second (scheduler, memory allocation, per-packet paths) costs real CPU. Prefer tracepoints and fentry over kprobes, filter in the kernel before sending events to user space, and prefer per-CPU maps on hot paths. Uprobes are the most expensive, because each hit traps from user space into the kernel.
11. Known risk classes
Section titled “11. Known risk classes”-
Verifier bugs. The verifier is large and has been wrong. Each of these let a program that passed verification read and write kernel memory:
- CVE-2020-8835: wrong 32-bit register bounds, Linux 5.5 and stable 5.4, fixed in 5.6.1.
- CVE-2021-3490: wrong 32-bit bounds for bitwise operations, fixed in 5.13-rc4.
- CVE-2023-2163: incorrect path pruning, kernels from 5.4, leading to container escape.
The first two were reachable by unprivileged users where unprivileged BPF was enabled. This is the main reason it is now off by default.
-
Speculative execution. Unprivileged BPF let an attacker place chosen code in the kernel, which made Spectre-class attacks practical. The verifier adds mitigations for unprivileged programs, and the kernel configuration help text gives this as the reason for the default-off setting.
-
eBPF rootkits. With load privileges an attacker needs no kernel module: programs can hide processes and files by rewriting syscall results in user memory, intercept credentials, open a network backdoor at XDP level before any firewall sees the packet, and survive through pinned objects. Lockdown integrity mode removes the user-memory write. The rest depends on not handing out the capabilities.
-
Supply chain. The agent you installed on purpose has all of this power. Its image, its Helm chart and its update channel deserve the same review as a kernel module.
Compare
Section titled “Compare”Tools that touch the kernel or hardware directly.
| Mechanism | What can go wrong | What limits it | How to audit it |
|---|---|---|---|
| eBPF programs | data exposure across all tenants on the node; tampering through write, override and signal helpers; verifier bugs leading to kernel code execution; CPU overhead on hot hooks | capabilities, unprivileged_bpf_disabled, verifier, lockdown, seccomp, LSM, BPF tokens, signatures (6.18) |
bpftool prog/map/link/perf show, audit BPF records, /sys/fs/bpf |
| Kernel modules | unrestricted native kernel code: any bug is a panic or memory corruption, any malice is a full rootkit; breaks on kernel upgrades | CAP_SYS_MODULE, module signature enforcement (module.sig_enforce, lockdown), kernel.modules_disabled=1 after boot |
lsmod, /proc/modules, modinfo, taint flags in /proc/sys/kernel/tainted, audit on init_module and finit_module |
| Privileged containers, hostPath and host device access | privileged: true grants all capabilities, all devices and no seccomp: mount the host disk, load modules, enter host namespaces. A writable hostPath to /, the runtime socket or /dev is the same thing |
Pod Security Standards, admission policy, user namespaces (hostUsers: false), read-only and narrow hostPath, device cgroup allowlist |
kubectl get pods -A -o json filtered on privileged, hostPID, hostPath; crictl inspect; capsh --decode on CapEff from /proc/<pid>/status |
| Kernel bypass and async I/O (DPDK, AF_XDP, SPDK, io_uring) | DPDK and SPDK take the device away from the kernel: no netfilter, no tc, no kernel counters, and the process needs hugepages and direct device access. io_uring stays in the kernel but exposes a large, fast-moving interface that has had many privilege escalation bugs | dedicated nodes and NICs, SR-IOV virtual functions with the IOMMU on, vfio in place of raw memory access, seccomp to block io_uring_setup where not needed |
dpdk-devbind.py --status, lspci -k (which driver owns the device), /proc/<pid>/maps for hugepage mappings, seccomp profile review |
| Device plugins (GPU, FPGA, SR-IOV) | a vendor kernel module plus a privileged DaemonSet on every node; device memory may keep data between tenants; a large driver ioctl surface is exposed to every pod that gets the device | signed vendor drivers, device cgroup limited to the allocated device, no sharing of one device across trust boundaries, dedicated node pools, sandboxed runtimes for untrusted tenants | kubectl describe node (allocatable extended resources), plugin pod spec, lsmod, nvidia-smi or the vendor tool, /var/lib/kubelet/device-plugins/ |
Ways to get custom logic into the kernel path.
| Classic BPF | eBPF | Kernel module | Upstream kernel patch | User-space agent (ptrace, audit, /proc) |
|
|---|---|---|---|---|---|
| Safety check before running | simple validity check | verifier | none | code review | n/a, runs outside the kernel |
| Can crash the kernel | no | not by design | yes | yes | no |
| Portability across kernel versions | high | high with CO-RE for stable hooks | rebuild per kernel | n/a | high |
| Time to deploy | seconds | seconds | minutes, plus build pipeline | months to years | seconds |
| Overhead per event | very low | low | lowest | lowest | high: context switches per event |
| Still used for | tcpdump filters, seccomp |
most new work | hardware drivers, file systems | core features | debuggers, compliance logging |
What breaks
Section titled “What breaks”| Symptom | Cause | Check |
|---|---|---|
bpf: Operation not permitted (EPERM) on load |
missing CAP_BPF, CAP_PERFMON or CAP_NET_ADMIN; seccomp denies bpf; lockdown; running in a user namespace without a token |
capsh --print, grep Seccomp /proc/self/status, cat /sys/kernel/security/lockdown, sysctl kernel.unprivileged_bpf_disabled |
Load fails with a long verifier log ending in invalid mem access, R1 type=... expected=... or unbounded memory access |
the program did not prove a bounds or NULL check | read the log from the last instruction upward; add the explicit check the verifier asks for |
BPF program is too large. Processed 1000001 insn |
verifier budget exhausted | split with tail calls or subprograms, reduce loop bounds |
Loads on one kernel, fails on another with failed to resolve CO-RE relocation or unknown func |
the field, helper or kfunc does not exist on that kernel, or the kernel has no BTF | ls /sys/kernel/btf/vmlinux, bpftool feature probe, uname -r |
kprobe attach fails: no such file or symbol not found |
the function was renamed or inlined in this kernel | grep -w FUNC /proc/kallsyms, bpftrace -l 'kprobe:FUNC*' |
| Tracing tools show nothing or fail under Secure Boot | lockdown confidentiality mode | cat /sys/kernel/security/lockdown, dmesg | grep -i lockdown |
| Agent pod OOMKilled soon after start | maps are charged to its memory cgroup | bpftool map show (memlock column), raise the limit or shrink max_entries |
| Node CPU rises after installing an agent | a probe on a hot path, or too many events sent to user space | sysctl kernel.bpf_stats_enabled=1, then bpftool prog show and sort by run_time_ns |
| Programs still loaded after the agent was removed | pinned in bpffs or held by a link | find /sys/fs/bpf, bpftool link show, remove the pin |
| Lost events | ring buffer full because user space reads too slowly | the agent’s own drop counter; enlarge the buffer or filter in the kernel |
Keywords
Section titled “Keywords”eBPF, BPF, classic BPF (cBPF), bpf() syscall, BPF_PROG_LOAD, bytecode, clang, LLVM, libbpf, cilium/ebpf, Aya, verifier, bounded loops, BPF_COMPLEXITY_LIMIT_INSNS, JIT, hook, kprobe, kretprobe, uprobe, USDT, tracepoint, raw tracepoint, fentry, fexit, BPF trampoline, perf event, XDP, XDP_DROP, XDP_REDIRECT, tc, cgroup BPF, sockmap, BPF LSM, struct_ops, sched_ext, BPF maps, ring buffer, perf buffer, LPM trie, tail call, helper, kfunc, BTF, CO-RE, vmlinux.h, bpffs, pinning, BPF link, CAP_BPF, CAP_PERFMON, CAP_NET_ADMIN, CAP_SYS_ADMIN, unprivileged_bpf_disabled, BPF_UNPRIV_DEFAULT_OFF, bpf_probe_read_kernel, bpf_probe_write_user, bpf_override_return, bpf_send_signal, kernel lockdown, integrity, confidentiality, signed BPF programs, BPF token, delegate_cmds, seccomp, Pod Security Standards, admission policy, bpftool, bpf_stats_enabled, AUDIT_BPF, memcg accounting, CVE-2020-8835, CVE-2021-3490, CVE-2023-2163, eBPF rootkit, Spectre, Cilium, Hubble, Tetragon, Falco, Pixie, Parca, Pyroscope, bpftrace, bcc, Katran, Inspektor Gadget, kernel module, DPDK, AF_XDP, io_uring, device plugin.
Sources
Section titled “Sources”- bpf(2) and bpf-helpers(7):
bpf_probe_write_user,bpf_override_return,bpf_send_signal - capabilities(7):
CAP_BPF,CAP_PERFMONsince Linux 5.8 - Kernel sysctl documentation:
unprivileged_bpf_disabled,bpf_stats_enabled - BPF design Q&A, kernel documentation: 1 million instruction limit, helpers and kfuncs, what programs may read and write
- LSM BPF programs, kernel documentation
- kernel_lockdown(7) and the lockdown reasons in include/linux/security.h
- Kernel source: kernel/bpf/Kconfig (
BPF_UNPRIV_DEFAULT_OFF), kernel/bpf/syscall.c (capability checks, audit records), include/linux/bpf.h (MAX_TAIL_CALL_CNT) - Kernel release notes: 3.18 (bpf syscall), 4.8 (XDP), 5.5 (BPF trampoline), 5.7 (BPF LSM), 5.8 (
CAP_BPF), 5.11 (memcg accounting), 6.9 (BPF tokens), 6.18 (signed programs) - Signed BPF programs, patch series cover letter
- BPF token, eBPF Docs
- What is eBPF, ebpf.io
- CVE-2020-8835, CVE-2021-3490, CVE-2023-2163
- Docker seccomp profile:
bpfis blocked by default - Kubernetes Pod Security Standards
- Cilium documentation, Tetragon enforcement, Falco kernel event sources
- McCanne and Jacobson, The BSD Packet Filter: A New Architecture for User-level Packet Capture (1992)