← Back to reference

Ebpf Security Model

What We Load

ProgramTypeAttach
oom_kill.bpf.ctracepointoom:mark_victim
page_fault.bpf.ctracepointexceptions:page_fault_user/kernel
block_io.bpf.ctracepointblock:block_rq_complete
tcp_retransmit.bpf.ctracepointtcp:tcp_retransmit_skb
gpu_process.bpf.cuprobelibcuda.so cudaLaunchKernel/Memcpy/StreamSync
nccl_socket.bpf.cuprobelibnccl.so ncclCommInitRank/AllReduce/Bcast/CommDestroy

Why This is OK

1. Verifier

All programs pass the kernel verifier before being loaded. Any unbounded loops or unbounded memory access is rejected.

2. No PII / No Process Memory Dump

Our programs emit only:

  • PIDs, comm (process name) — already public via /proc.
  • Latencies, addresses — already public via /proc/vmstat, /proc/<pid>/wchan.

We never read full instructions, full instruction pointers, or sensitive kernel struct fields beyond what the tracepoint already exposes.

3. Bounded Ringbuffers

Each program uses a 4MB ringbuffer (BPF_MAP_TYPE_RINGBUF). The user-space consumer caps at 1,000 events/sec with drop+counter on overflow. The maps have no unprivileged read.

4. Pinning

Pinned to /sys/fs/bpf/denpex/<program> with BPF_F_PIN_GLOBAL so a privileged re-attach doesn't lose history, but a malicious unprivileged user can't read or write the maps.

5. Signed Loader

denpex-bpf-loader is signed at build time and verified at boot via cosign / sigstore. A tampered loader refuses to load.

6. No Network Probes

The eBPF programs only emit events via the ringbuffer. They do not initiate network communication.

What We DON'T Load

  • Network XDP/TC programs.
  • kprobes into kernel modules outside the allow-list.
  • USDT probes anywhere outside the libc/libm allow-list.
  • LSM hooks (no BPF-LSM).

CI Test Path

For CI / non-Linux runners, the loader reports a capability_missing event for every program, and the agent falls back to journald-only collection. Tests still pass.