Papers
Topics
Authors
Recent
Search
2000 character limit reached

BeePL: Verified eBPF Language

Updated 4 July 2026
  • BeePL is a domain-specific language for eBPF that integrates a verification-oriented source language with a formally verified compiler to ensure kernel extension safety by design.
  • It employs a rigorous type system and restricted language constructs, enforcing key safety properties like termination, proper pointer handling, and bounded loops.
  • The verified compilation pipeline extends CompCert to generate eBPF bytecode, preserving source semantics and inserting dynamic checks only where static guarantees are insufficient.

Searching arXiv for the BeePL paper and closely related eBPF verification work. BeePL is a domain-specific language for eBPF together with a verified compilation framework for writing kernel extensions that are intended to be correct by compilation rather than safe only by post hoc acceptance from the in-kernel verifier. It is designed around the observation that the existing eBPF verifier is both overly conservative in some cases and unsound in others, and that mainstream source languages still leave crucial eBPF-specific safety obligations to the verifier. BeePL addresses this by combining a restricted, verification-oriented source language, a formally verified type system, source-level proofs of safety-relevant properties, and a verified compilation strategy that extends CompCert to generate BPF bytecode (Priya et al., 14 Jul 2025).

1. Origin, motivation, and problem setting

eBPF allows developers to extend kernel functionality without modifying kernel source code or writing loadable kernel modules, but the safety requirements are unusually strict because the kernel governs privileged state and isolation boundaries. The conventional safety mechanism is the eBPF verifier, which statically checks properties such as memory access validity, bounded loops, and type correctness before a program is loaded. BeePL is motivated by the claim that this verifier is not an adequate sole foundation for assurance: it is described as overly conservative in some cases, rejecting valid programs, and unsound in others, permitting unsafe behavior that violates the intended semantics of the kernel interface (Priya et al., 14 Jul 2025).

The paper grounds that critique in concrete bug classes and CVEs. It cites problems involving incorrect range tracking, pointer/null handling, shift/division/modulo corner cases, and out-of-bounds behavior, including CVE-2021-3600, CVE-2020-8835, CVE-2022-23222, CVE-2021-3490, CVE-2021-31440, and CVE-2020-27194. The central design response is not to strengthen the verifier directly, but to move much of the safety argument into a typed source language and a verified compiler pipeline.

This design changes the locus of trust. In BeePL, well-typed source programs are intended to satisfy a formalized set of eBPF-relevant properties before compilation, and compilation preserves their behavior while inserting semantics-preserving runtime checks where purely static guarantees are insufficient. The verifier still remains relevant as a compatibility gate for generated eBPF, but it is no longer the primary proof engine.

2. Language design, syntax, and static discipline

BeePL is a verification-friendly language with structured control flow, explicit optional pointers, references, mutable effects, structs, arrays, and byte-pattern matching for safe parsing. Its core typing judgment is

Γ,Σ,Π,Ψe:τ,η\Gamma,\Sigma,\Pi,\Psi \vdash e : \tau, \eta

where Γ\Gamma is the variable typing environment, Σ\Sigma is the store typing environment, Π\Pi is the struct environment, and Ψ\Psi is the external-function signature environment. Effects are tracked explicitly:

η{divergence, read, write, alloc, io}.\eta \in \{ divergence,\ read,\ write,\ alloc,\ io \}.

The type system is the primary static mechanism for enforcing eBPF-specific safety properties. BeePL types include primitive types, pointers, function types with effects, structs, arrays, bytes, and unit. A crucial distinction is made between references created internally by ref, which are guaranteed non-null, and nullable pointers returned by external helpers, which are modeled as option(\tau*). This makes nullability explicit and pushes null-safety obligations into the type system.

The language excludes several patterns that are common in lower-level eBPF programming but difficult to verify compositionally. Primitive operators are restricted to primitive types, which rules out pointer arithmetic in source BeePL. Functions cannot return pointer types. The dereference and assignment rules exclude optional pointers, so an option(\tau*) value cannot be dereferenced until it has been eliminated by pattern matching. In the paper’s presentation, dereference is typed only when the pointer is not optional:

$\inferrule*[left={TDEREF}] {\Gamma,\Sigma,\Pi,\Psi \vdash e : \tau_e^*,\eta \quad \tau_e^* \neq option(\_*)} {\Gamma,\Sigma,\Pi,\Psi \vdash !e : \tau_e, (read :: \eta)}.$

Loops are restricted to bounded for loops. The loop bounds must be numeric, and the body is prevented from modifying the variables that determine the range. The paper encodes this with a free-variable side condition in the TFOR rule. Combined with the absence of arbitrary recursion, this yields a source language in which termination is a built-in design property rather than an emergent verifier judgment (Priya et al., 14 Jul 2025).

3. Operational semantics and formal source-level guarantees

BeePL is formalized with a small-step operational semantics over states s=Δ,Ω,Θs = \langle \Delta,\Omega,\Theta \rangle, where Δ\Delta is the global environment, Ω\Omega maps local variables to locations and types, and Γ\Gamma0 is memory. The memory model is inherited from CompCert. This semantic layer is important because BeePL’s safety claims are not stated merely as typing intuitions; they are proved against an explicit execution model (Priya et al., 14 Jul 2025).

A distinctive semantic choice is the elimination of C-style undefined behavior for problematic arithmetic. Binary operations are given totalized semantics through an unsafe predicate:

Γ\Gamma1

This means that division, modulo, and shift operations do not become undefined when their usual preconditions fail; instead, they evaluate to Γ\Gamma2. That source-level semantics is later preserved by compilation-time insertion of explicit guards.

The paper proves the standard type-soundness triad: progress, preservation, and soundness. It then strengthens the result with eBPF-specific safety theorems. For well-typed programs started in well-formed states, the paper states source-level guarantees including no uninitialized memory access, no null pointer dereferences, memory bounds safety for structured byte parsing, compliance with helper signatures and section attributes, termination, and absence of undefined behavior.

Termination is stated explicitly as:

Γ\Gamma3

Similarly, the absence of undefined behavior is stated as:

Γ\Gamma4

Byte-pattern matching is the formal basis for parser safety. Successful extraction requires the buffer to be large enough for the requested type; otherwise execution takes a fallback branch. This is the source-level reason BeePL can claim bounds-safe packet parsing without relying on the verifier to rediscover those conditions.

4. Runtime checks and verified compilation pipeline

BeePL does not claim that every safety property can be enforced statically. The paper distinguishes between properties enforced by the language and type system and properties that require semantics-preserving runtime checks inserted during compilation. Statically enforced properties include type-correct memory access, safe pointer usage, absence of unbounded loops, structured control flow, helper-signature discipline, and the prohibition of unchecked dereference of nullable pointers. Dynamic checks are inserted for properties “not fully enforceable statically,” including dynamic bounds checks and undefined arithmetic corner cases (Priya et al., 14 Jul 2025).

The compilation pipeline is staged. BeePL source is parsed into an AST, typechecked, compiled to CompCert’s Csyntax, then lowered by an extended CompCert backend to eBPF bytecode. The BeePL compiler is implemented in Rocq and extracted to OCaml, while the parser, lexer, and pretty-printer remain in the trusted computing base. The CompCert extension for the eBPF backend contributes 33,635 lines of Rocq code.

The inserted checks mirror source semantics. Optional-pointer matching compiles to null checks. Byte matching compiles to explicit bounds checks. Arithmetic operations that would be unsafe in C or eBPF are rewritten into guarded expressions that preserve BeePL’s source meaning, such as compiling modulo into a conditional form equivalent to “if divisor is zero then 0 else modulo.”

The paper’s main semantic-preservation theorem for the BeePL-to-Csyntax translation states that if a BeePL expression evaluates to a value Γ\Gamma5 from source state Γ\Gamma6, then the compiled Csyntax program evaluates to the same value Γ\Gamma7, and the resulting states remain related by a source–target equivalence relation:

Γ\Gamma8

The extension of CompCert to eBPF is itself a systems contribution. The backend accounts for differences between conventional targets and eBPF, including stack handling around the read-only architectural stack pointer register Γ\Gamma9, the lack of support for general signed arithmetic in the target ISA, and restrictions such as no support for Mach Mtailcall or Mgetparam. Under those restrictions, the backend is stated to be proved correct within CompCert’s framework.

5. Relationship to the verifier and to existing eBPF workflows

BeePL is best understood as a reconfiguration of the standard eBPF workflow rather than as a mere surface-language alternative. In conventional C-based eBPF development, safety depends heavily on the verifier, and the source language does not itself encode most eBPF-specific obligations. Rust improves source-level memory safety but, in the paper’s account, still lacks verified BPF compilation and does not prove eBPF-specific properties such as guaranteed termination. Honey Potion and Elixir are presented as systems that can reason about termination and stack discipline in practice, but without BeePL’s formal guarantees. VEP retains more of the C ecosystem, but depends on annotations and does not formally verify preservation through compilation (Priya et al., 14 Jul 2025).

BeePL’s comparison point is therefore not just expressiveness but assurance structure. The verifier is criticized on both precision and soundness grounds. Over-conservatism stems from finite abstract interpretation under strict resource limits, especially the state splitting caused by branches. Unsoundness arises from bugs in range analysis, pointer tracking, and ALU32 handling. BeePL responds by making the source language itself respect the safety envelope required by eBPF.

The examples tied to specific CVEs illustrate this change in methodology. For divide/modulo-by-zero due to truncation, BeePL gives safe source semantics and compiles guarded code. For unsafe shift amounts, it inserts explicit bounds checks. For nullable helper returns, it uses option(\tau*) and requires pattern matching before use. The result is a workflow in which the source program, type system, semantics, and compiler collectively establish the safety case, rather than delegating that burden almost entirely to an evolving in-kernel analyzer.

6. Scope, restrictions, and significance

BeePL achieves its guarantees by accepting significant restrictions. It has no arbitrary recursion, only restricted bounded for loops, no pointer arithmetic in source, no pointer-returning functions, no current stack-usage or frame-size analysis, and no verification of helper correctness. Byte-pattern matching currently focuses on structs with non-pointer fields. These are deliberate design tradeoffs rather than incidental limitations (Priya et al., 14 Jul 2025).

Those tradeoffs define the scope of the language. BeePL is not intended as a drop-in replacement for general-purpose C in all eBPF domains. It is instead a language and verified toolchain for the subset of kernel-extension programming where strong static structure is acceptable and where eBPF-specific safety obligations dominate concerns about maximal expressiveness.

Its significance lies in the phrase “correct-by-compilation.” BeePL’s central contribution is not a new verifier and not merely a safer frontend, but an end-to-end argument structure: a typed, effect-aware source language establishes safety-relevant invariants; dynamic checks are inserted only where static enforcement is insufficient; the front-end translation to Csyntax preserves source meaning; and an extended, proved-correct CompCert backend carries that meaning down to eBPF bytecode. Within that scope, BeePL redefines safe kernel extension development as a compilation problem with proofs rather than a verifier-acceptance problem with heuristics.

Definition Search Book Streamline Icon: https://streamlinehq.com
References (1)

Topic to Video (Beta)

No one has generated a video about this topic yet.

Whiteboard

No one has generated a whiteboard explanation for this topic yet.

Follow Topic

Get notified by email when new papers are published related to BeePL.