§ ebpf

Verifier

How axiomOS proves an eBPF program safe before running it.

The verifier is the contract between userspace and the kernel: bytecode that cannot be proven safe is never executed. The current implementation performs control-flow analysis, abstract interpretation with tnum and range refinement, per-instruction liveness, and state pruning.

Pipeline

1. parse bytecode → instructions
2. build control-flow graph (CFG)
3. assert termination
     · every back-edge requires a bounded-iteration witness
4. abstract interpret
     · tnum (known-bits) tracking
     · signed/unsigned range tracking
     · range refinement after conditional branches
5. assert invariants
     · stack depth ≤ profile limit
     · memory accesses fall within registered regions
     · all paths terminate
6. emit Verified { bytecode, summary } | VerifyError

Skeleton

fn verify_program(bytecode: &[u8]) -> Result<Verified, VerifyError> {
    let cfg = build_cfg(bytecode)?;

    for node in cfg.nodes() {
        if has_backedge(node) && !has_bounded_iter(node) {
            return Err(VerifyError::UnboundedLoop);
        }
    }

    let abs = abstract_interpret(&cfg)?;
    abs.assert_stack_depth(STACK_LIMIT)?;
    abs.assert_memory_access(&cfg)?;

    Ok(Verified { bytecode, abs })
}

Profiles

The same verifier supports multiple physical-reality profiles. Embedded profile caps the stack at 8 KB and disables the JIT; cloud profile permits 512 KB and enables aarch64 JIT. Selection is at compile time via sealed traits.

#[cfg(feature = "embedded-profile")]
type BpfProfile = profile::EmbeddedProfile;

#[cfg(feature = "cloud-profile")]
type BpfProfile = profile::CloudProfile;

What the verifier guarantees

  • Termination. No path runs forever.
  • Bounded stack. Static bound on stack growth.
  • Validated memory access. Every load and store hits a registered region with a verified size.
  • Helper signature conformance. Helper calls take and return values within declared types.

What the verifier does not guarantee

  • Functional correctness. A program may be safe yet useless.
  • Wall-clock bounds. Termination ≠ promptness; profile-level instruction caps are used at execution.