Skip to content

eBPF

eBPF (extended Berkeley Packet Filter) runs programs safely in the Linux kernel without kernel modules or source code modifications. Originally designed for packet filtering, it now serves as a general-purpose execution engine for security, networking, and observability tools.

For comprehensive eBPF documentation, see ebpf.io and docs.ebpf.io.

Why eBPF for Security

Traditional approaches to kernel visibility involve trade-offs:

ApproachLimitation
Kernel modules
  • Can crash the system
  • Difficult to maintain across kernel versions
Ptrace / strace
  • 10-100x overhead
  • Single-process only
  • Detectable by traced process
Sys monitoring
  • Limited to /proc and /sys
  • High context-switch cost
  • Bypassable
Fanotify
  • Introduces kernel latencies
  • Limited to filesystem events
Audit
  • High even volume causes backlog overflow and event loss
  • Parsing overhead
  • Not real-time
Inotify
  • No recursive directory monitoring
  • Watch descriptor exhaustions
Seccomp (without eBPF)
  • Static filter rules
  • No runtime context
  • Kill-or-allow decisions only
Kprobes / Tracepoints (without eBPF)
  • Needs kernel module for complex logic
  • No verifier safety
  • Stability concerns

Some tools use these kernel features to achieve visibility, but they introduce additional overhead and complexity and are not as secure and reliable as eBPF.

eBPF provides kernel-level visibility without these limitations

  • Built-in verification preventing crashes
  • Near-zero overhead through JIT compilation
  • Portability across kernel versions via CO-RE
  • Sandboxed execution environment

How eBPF Works

Execution Flow

StepPhaseDescription
1Load ProgrameBPF bytecode submitted to kernel
2VerifyKernel validates memory safety, termination, and resource bounds
3JIT CompileBytecode compiled to native machine code
4Attach HooksProgram attached to kernel hook points (syscalls, network events, tracepoints)
5ExecuteProgram runs in response to events, storing data in maps
Graphical Flow

Program Types

eBPF supports multiple program types for different use cases:

Program TypeUse Case
Kprobes / KretprobesKernel function entry and exit
Socket filtersNetwork packet processing
TracepointsStatic kernel instrumentation points
XDPNetwork packet processing
Cgroup filtersResource management
LSMLinux Security Module hooks

Maps

eBPF maps are data structures shared between kernel and userspace:

Map TypeUse Case
Hash mapsKey-value storage for event metadata
Array mapsIndexed storage for configuration
LRU mapsBounded storage with automatic eviction
Ring buffersEvent streaming to userspace
Perf event arraysEvent streaming to userspace

Verifier

The eBPF verifier performs static analysis before loading:

  • Validates all code paths terminate
  • Checks memory access bounds
  • Ensures no unauthorized kernel memory access
  • Rejects programs that fail safety checks

Safe Execution

Programs that pass verification cannot crash the kernel. The verifier guarantees safe execution.

Portability

CO-RE (Compile Once, Run Everywhere)

CO-RE enables eBPF programs to run across kernel versions without recompilation:

  • Automatic struct field relocation
  • Kernel version differences handled at load time
  • No per-kernel compilation required

BTF (BPF Type Format)

BTF provides type information for eBPF programs:

  • Enables CO-RE relocations
  • Improves debugging and introspection
  • Required for portable programs

How Jibril Uses eBPF

Events, collected by eBPF programs from multiple sources, are stored in eBPF maps and retrieved on demand by the userspace runtime.

See Architecture for details on the query-driven model.

Next Steps