← All posts

eBPF vs kernel modules: why it matters for Linux EDR

How a Linux EDR collects kernel telemetry - eBPF, kernel modules, or plain syscall interfaces - has real consequences for stability, portability, and attacker evasion.

When you’re picking an EDR for Linux endpoints, one question most buyers skip is: how does this agent actually collect telemetry from the kernel? The answer - eBPF, a kernel module, or standard kernel interfaces - has real consequences for stability, update complexity, and what an attacker can do to blind your detection coverage.

What kernel modules do and why they’re risky

Kernel modules (.ko files) are pieces of code that run directly in kernel space, with unrestricted access to system memory and hardware. They load at runtime and can do essentially anything: intercept system calls, modify kernel data structures, hook into the VFS layer for filesystem events.

For an EDR, that’s appealing. Intercepting execve() at the kernel level means you see every process launch before it executes, with no chance of user-space evasion. The problem is that this power comes with two significant drawbacks.

Stability risk. A bug in a kernel module crashes the entire system - there is no safety net. This is why a poorly implemented EDR agent can produce the kind of kernel panics that take down production infrastructure. If you have seen “EDR caused an outage” incident reports, kernel module bugs are usually the culprit.

Kernel version coupling. Modules are compiled against a specific kernel version. Every kernel update potentially requires a recompile and retest cycle. In environments with rolling kernel updates or heterogeneous distributions (CentOS 7, RHEL 8, Ubuntu 22.04, and a handful of Alpine containers all on the same estate), this quickly becomes a maintenance burden.

What eBPF does differently

eBPF (extended Berkeley Packet Filter) is a sandboxed bytecode VM built into the Linux kernel since 3.18, with major capability additions through 5.x. You write eBPF programs in restricted C, compile them to bytecode, and the kernel’s verifier checks them before loading - ensuring they cannot crash the kernel, cannot loop indefinitely, and cannot access arbitrary memory.

Once loaded, eBPF programs run in kernel context with JIT compilation, so overhead is low. They hook into system call entries and exits, tracepoints, kprobes, and network events, then pass data to user space via ring buffers. A minimal example that attaches to the execve syscall entry:

SEC("tracepoint/syscalls/sys_enter_execve")
int trace_execve(struct trace_event_raw_sys_enter *ctx)
{
    struct event e = {};
    e.pid = bpf_get_current_pid_tgid() >> 32;
    bpf_get_current_comm(&e.comm, sizeof(e.comm));
    bpf_ringbuf_output(&events, &e, sizeof(e), 0);
    return 0;
}

The key differences from kernel modules:

  • Crash-safe. The verifier rejects programs that could destabilise the kernel before they ever load.
  • Portable with CO-RE. With BTF (BPF Type Format) and CO-RE (Compile Once, Run Everywhere), a single eBPF binary runs across different kernel versions without recompilation - you ship one artefact, not a build per kernel.
  • Revocable cleanly. eBPF programs unload without a system restart.

For security telemetry, eBPF has become the preferred approach in modern open-source projects (Falco, Tetragon, Cilium) and in most commercial EDR vendors’ Linux agents.

Practical trade-offs to know

eBPF is not constraint-free. Full CO-RE/BTF support requires kernel 5.8 or later. Older distributions - RHEL 7 with a 3.10 kernel, Ubuntu 18.04 on 4.15 - have very limited eBPF support. An EDR that relies entirely on eBPF may have reduced coverage on those hosts, or may fall back to a kernel module on older systems anyway.

Kernel module eBPF
Crash risk on bug High (kernel panic) Low (verifier blocks unsafe code)
Kernel version coupling High Low with CO-RE (kernel 5.8+)
Performance overhead Low-moderate Low (JIT compiled)
Attacker tamper surface Larger (rootkit target) Smaller
Minimum kernel Any 4.18+ (limited), 5.8+ (full)
Secure Boot signing required Yes (on most distros) No

The Secure Boot point is worth noting: on distributions that enforce kernel module signature verification (RHEL 8+ with Secure Boot enabled, most modern enterprise distros), loading an unsigned third-party kernel module either requires disabling Secure Boot or paying for vendor signing. eBPF programs do not require kernel module signatures.

Questions to ask your EDR vendor

Before committing to a Linux EDR, these are worth asking:

  • Does the agent use eBPF, a kernel module, or standard kernel interfaces? If both, when does each apply?
  • What is the minimum supported kernel version? What happens to telemetry below that?
  • Does the agent require kernel module signing for Secure Boot environments?
  • Has the agent caused a kernel panic in production? How was that resolved and what changed?

The goal is not to disqualify vendors that use kernel modules - it is to understand the operational risk profile before an incident puts those answers under pressure.

LightEDR’s agent is a sub-40 MB static binary with no kernel module required for standard telemetry collection. If you want to know how that translates to your specific Linux estate and kernel versions, get in touch.