Made by rpmn0ise https://rpmn0ise.neocities.org/

eBPF Subsystem Architecture

Notes on Helper Functions and Maps in Modern Kernels


1. Scope and Intent

This document is a knowledge base entry about the internal architecture of the eBPF subsystem, with a focused view on helper functions and maps as implemented in modern Linux kernels (roughly 5.x and newer).

It is written for technically experienced readers who already understand basic kernel concepts (syscalls, memory protection, networking stack, tracing) and want a clearer mental model of how eBPF programs interact with the kernel safely and efficiently.

This is not a tutorial, not a performance guide, and not an advocacy text.
The goal is understanding structure, constraints, and design trade-offs.


2. High-Level Architecture Reminder

At a high level, eBPF consists of:

  • A restricted virtual machine executed inside the kernel
  • A verifier enforcing safety and termination
  • Program types attached to specific kernel hooks
  • Helper functions acting as controlled syscalls
  • Maps acting as persistent shared state

From an architectural point of view:

  • Helpers are actions
  • Maps are memory

Everything an eBPF program does outside its local stack goes through one of these two abstractions.


3. Helper Functions: Controlled Kernel Entry Points

3.1 Definition

Helper functions are kernel-provided functions that an eBPF program may call.
They are the only legal way for an eBPF program to:

  • Interact with kernel subsystems
  • Access contextual data beyond the immediate program context
  • Emit data to user space
  • Allocate or manipulate kernel-managed objects

Helpers are not dynamically callable.
Each helper is:

  • Identified by a numeric ID
  • Whitelisted per program type
  • Statically validated by the verifier

3.2 Design Rationale

The helper model exists to enforce:

  • Capability-based access
  • Explicit trust boundaries
  • Stable ABI contracts

Unlike syscalls:

  • Helpers are not generic
  • They expose narrow, purpose-built semantics
  • They are tightly bound to the execution context

This reduces kernel attack surface while still allowing expressive programs.


3.3 Helper Categories (Conceptual)

Helpers can be grouped by intent rather than implementation.

Context Access Helpers

Used to read or interpret the execution context.

Examples:

  • Packet data access in XDP or TC
  • Register or stack inspection in tracing programs

Constraints:

  • Read-only or limited write access
  • Bounds enforced by verifier and runtime checks

State Manipulation Helpers

Used to interact with maps or kernel-managed state.

Examples:

  • Map lookup, update, delete
  • Per-CPU data access

These helpers are heavily constrained to prevent aliasing or lifetime errors.

Event and Output Helpers

Used to communicate with user space or other kernel paths.

Examples:

  • Ring buffer submission
  • Perf event output
  • Trace printing (primarily for debugging)

These helpers often introduce observable overhead and are not guaranteed to be lossless.

Time and Randomness Helpers

Used to access kernel time or pseudo-random values.

Important limitation:

  • No guarantees about monotonicity or entropy quality beyond kernel guarantees.

3.4 Verifier Interaction

The verifier reasons about helper calls in detail:

  • Argument types must be known at verification time
  • Pointer provenance is tracked across helper calls
  • Return values may be constrained or marked as nullable

A helper call can invalidate assumptions:

  • A pointer returned from a helper is often marked as unknown until checked
  • Failure paths must be explicitly handled

This is a common source of rejected programs.


3.5 Stability and Evolution

Helper functions are append-only from a user perspective:

  • Existing helpers cannot change semantics
  • New helpers are added cautiously
  • Some helpers are program-type specific and never generalized

However:

  • Availability depends on kernel version
  • CO-RE does not abstract helper availability
  • Runtime feature probing is often required

4. Maps: Shared, Persistent State

4.1 Definition

Maps are kernel-resident data structures accessible by:

  • One or more eBPF programs
  • User space via file descriptors

They represent the only form of persistent state across program invocations.

Maps are created by user space and referenced by programs.


4.2 Architectural Role

Maps serve multiple roles simultaneously:

  • Data storage
  • Synchronization boundary
  • ABI between kernel and user space
  • State transfer across hooks

This multiplexing is powerful but creates design tension.


4.3 Core Map Properties

Every map is defined by:

  • Key type and size
  • Value type and size
  • Maximum number of entries
  • Map type
  • Optional flags (per-CPU, NUMA-aware, read-only)

These properties are immutable after creation.


4.4 Common Map Types (Conceptual Overview)

Hash Maps

General-purpose key-value storage.

Trade-offs:

  • Flexible
  • Non-deterministic iteration
  • Memory overhead per entry

Used for:

  • Flow tracking
  • State correlation
  • Dynamic sets

Array Maps

Index-based storage with fixed size.

Trade-offs:

  • Predictable access
  • No dynamic growth
  • Index must be known or computed

Often used for:

  • Configuration
  • Counters
  • Lookup tables

Per-CPU Maps

Replicated values per CPU.

Benefits:

  • Avoid contention
  • Lock-free access patterns

Costs:

  • Increased memory usage
  • Aggregation required in user space

Ring Buffer Maps

Sequential data transfer to user space.

Characteristics:

  • One-way communication
  • Loss possible under pressure
  • Designed for events, not state

4.5 Memory and Lifetime Semantics

Map memory is:

  • Managed by the kernel
  • Accounted against memory limits
  • Not directly addressable by user space

Important constraints:

  • No unbounded allocation
  • No pointer persistence across helper calls unless explicitly allowed
  • Map values may be copied, not referenced

Maps can outlive programs but are destroyed when all references are closed.


4.6 Concurrency Model

Maps are not transactional.

Concurrency rules depend on map type:

  • Some maps provide implicit locking
  • Per-CPU maps avoid locking by replication
  • Atomic operations are limited and explicit

Design implication:

  • Consistency is the programmer’s responsibility
  • Many designs accept eventual consistency

5. Helpers and Maps Together

The helper–map interaction is central to eBPF design.

Key observations:

  • Maps are never accessed directly
  • All map operations go through helpers
  • Helper semantics define allowed access patterns

The verifier tracks:

  • Which map is accessed
  • With what key/value types
  • In which control-flow paths

This tight coupling allows aggressive static checking.


6. BTF, CO-RE, and Type Awareness

Modern kernels expose BTF (BPF Type Format):

  • Kernel type metadata
  • Program type introspection
  • Safer access to complex structures

Implications for helpers and maps:

  • Helpers can be type-aware
  • Map values can reference structured data
  • CO-RE allows portable field access, not portable helpers

Limits remain:

  • Not all helpers are BTF-described
  • Kernel internal layout changes still matter

7. Security Model and Limitations

eBPF is designed to be:

  • Non-Turing complete (bounded loops only)
  • Memory safe
  • Non-crashing to the kernel

However:

  • Complexity increases attack surface
  • Helpers are frequent audit targets
  • Map misuse can cause denial-of-service patterns

Common limitations:

  • No unbounded loops
  • No dynamic memory allocation
  • No direct kernel pointer arithmetic
  • No floating-point operations

These are design choices, not omissions.


8. Practical Design Trade-Offs

When designing around helpers and maps:

  • Fewer helpers means safer programs, but less expressiveness
  • More maps improve modularity, but increase overhead
  • Per-CPU maps improve scalability, but complicate aggregation
  • Ring buffers simplify output, but drop data under load

There is no universal “best” structure.


9. Areas of Active Evolution

As of modern kernels:

  • New helpers are added conservatively
  • Map types evolve faster than helpers
  • Verifier precision improves gradually
  • Tooling (bpftool, libbpf) carries much of the complexity

Kernel documentation often lags implementation.

Reading kernel source remains necessary for deep understanding.


10. Summary

Helper functions and maps are not implementation details.
They are the architecture of eBPF.

  • Helpers define what is allowed
  • Maps define what can persist
  • The verifier defines what is safe

Understanding their constraints is more important than memorizing APIs.

For advanced usage, thinking in terms of capabilities and invariants is more productive than thinking in terms of features.


Made by rpmn0ise https://rpmn0ise.neocities.org/

Edit

Pub: 23 Jan 2026 11:44 UTC

Edit: 23 Jan 2026 11:55 UTC

Views: 6