- The paper introduces Heimdall, a framework that formally verifies semantic equivalence between migrated eBPF C programs and their Rust translations.
- It employs a five-stage pipeline combining LLM-assisted translation, static safety analysis, and symbolic execution to identify and repair safety gaps in legacy code.
- Empirical evaluation on 102 programs shows 94.1% full verification success and validates runtime fidelity with only a minimal 1.25× overhead.
Problem Statement and Motivating Analysis
The Extended Berkeley Packet Filter (eBPF) subsystem supports a performance-critical, production-grade extension model for the Linux kernel, underpinning observability, security enforcement, and networking primitives. While the kernel's in-tree eBPF verifier admits only programs with provable memory safety and termination, its guarantees are circumscribed: it accepts programs with uninitialized memory leaks, unchecked helper return values, buffer-size mismatches, context-type confusions, map-schema inconsistencies, and silent signed/unsigned conversion bugs. These gaps enable persistent information leaks (stack residue, cross-record event leaks) and correctness faults, which can propagate through production platforms and defeat system-level defences (e.g., Kernel Address Space Layout Randomization).
The paper identifies six structural classes of source-level bugs that compile, load, and execute under the available verifier, but nonetheless yield silent misbehaviours or kernel information disclosure. Empirical analysis of real-world eBPF programs (across libbpf-tools, libbpf-bootstrap, and Ken) confirms the prevalence of these bugs, including the defeat of KASLR through bashreadline stack leaks, and the exposure of per-user credentials via mountsnoop ring-buffer leakage.
Heimdall: Automated Migration Pipeline
Heimdall operationalizes the migration of verifier-accepted, potentially unsafe C eBPF programs to idiomatic, memory-safe Rust (using the Aya framework). The pipeline combines LLM-assisted translation, static safety analysis, compilation and kernel-verifier repair, bytecode-level symbolic execution, and formal semantic equivalence checking (via Z3) in an iterative loop.
The translation workflow proceeds through five stages:
- LLM Translation: C libbpf programs are prompted through a staged LLM prompt to Aya Rust, with explicit mappings for hook types, map accessors, and helper abstractions.
- Compile and Kernel Verify: The Rust output is compiled to eBPF bytecode; compilation and verifier errors are fed back to the LLM for iterative repair.
- Static Safety Analysis: A bespoke analyzer rejects unsafe patterns (untyped ring-buffer reservations, unchecked helper returns, unsafe extern trampolines) not covered by the Rust type system or the kernel verifier.
- Symbolic Execution: Both the original C and Rust binaries are loaded into an enhanced angr backend, which models eBPF helpers, maps, atomic operations, and subprogram calls, and emits structured path predicates and side effects.
- Formal Equivalence Checking: Z3 asserts semantic equivalence on observable behavior (return values, map updates, output sinks), with counterexample-guided repair upon divergence.
Heimdall supports both deterministic and agentic instantiations: the former executes via a scripted pipeline with stateless LLM calls, while the latter invokes a tool-mediated agent framework capable of file browsing, in-context code search, subagent orchestration, and binary inspection.
Heimdall introduces a systematic symbolic execution backend for eBPF, extending angr's loading, architectural description, instruction lifting, helper modeling, and path summarization.
(Figure 1)
Figure 1: Overview of Heimdall's tool-call distribution by main agent and subagent across the 96 verified programs.
The pipeline leverages a custom if-then-else chain encoding to soundly model last-write-wins map semantics under symbolic key aliasing, enabling full precision for helpers, perf buffers, and ringbuf output. The formal definition of semantic equivalence is conditional: equivalence is asserted only on inputs that do not trigger source-level bugs closed by migration (e.g., only on helper-success paths, ignoring opaque sink bytes).
Empirical Results and Benchmarking
Evaluation encompasses 102 real-world eBPF programs from production, open source, and research sets, excluding those unsupported by Aya (e.g., cgroup_array, legacy socket-filter). Heimdall (Agentic) achieves 94.1% fully verified translations (96/102), with partial verification in three others due to symbolic execution scaling limits.
Benchmark comparisons across baseline LLM agents, deterministic Heimdall, and agentic Heimdall reveal:
- Baseline LLM approaches yield compilation-only output with <20% formal equivalence.
- Agentic Heimdall increases verified output rates by up to 90 percentage points, with bytecode overhead averaging 2.89×; unsafe operations in Rust translations average 18.3 per program.
- Safety analysis closes all observed uninitialized state, unchecked helper return, and signed–unsigned conversion bugs in the verified subset.
- Runtime validation via 1,000 paired trials on 10 programs yields 100% exact match in filtered-record counts, with median Rust-to-C runtime overheads of 1.25×, confirming fidelity of the translated programs.
Figure 2: Tool-call distribution for verified programs, illustrating main-agent and subagent tool activity.
Figure 3: Purpose distribution for 68 subagent invocations over 48 programs, highlighting targeted framework and header lookups.
Implications and Future Directions
The practical impact of Heimdall is the closure of critical eBPF safety gaps through language migration, without loss of kernel functionality or observable side effects. Its equivalence proof methodology aligns with compiler translation validation frameworks and complements prior work on eBPF verifier analysis, runtime checks, and proof-carrying code.
Theoretically, Heimdall introduces a scalable bytecode-level equivalence model suitable for map-heavy, event-driven kernel programs, and a formal safety-policy enforcement strategy bridging source and runtime. Future research may pursue compositional symbolic reasoning for scalability, integrate performance optimization feedback (e.g., bytecode size and execution time), and extend frontend coverage to non-C eBPF sources.
Conclusion
Heimdall represents a comprehensive, formally verified framework for automated migration of legacy eBPF programs from C to Rust/Aya. It advances the field by enforcing per-program semantic equivalence at the bytecode level, bridging gaps in kernel extension safety beyond verifier guarantees, and supplying open benchmarks for agentic translation. The framework's synthesis, verification, and safety-analysis techniques are modular and applicable to analogous domains requiring robust, verifiable migration from unsafe to memory-safe languages (2605.25411).