Skip to Content
Viewing feat/v0.5-runtime docs — not the stable branch. Changes vs main · Go to main

Threat Model

Relevant source files

The threat model is a living document whose line citations refer to commit f2e38bc (2026-07-03). It carries an audit erratum, and several of its gaps have since been addressed in code. This page summarizes it and marks where the code has moved on.

Audit erratum (2026-07-11), as recorded in the source document: at the audited commit (C-01) user-pointer validation was numeric only, (C-06) JIT pages were RWX and recompiled per hook fire, and (H-02) the x86 clock treated HPET ticks as nanoseconds. On feat/v0.5-runtime, user copies go through the page-walking kernel_usermem contract (Memory), and both shipped profiles set JIT_ALLOWED = false with a test asserting it stays false “until C-06 redesign”. H-02 is why legacy x86 QEMU timings are invalid (Current Results).

Assets

AssetLocationNotes
Kernel imagekernel/ (Limine on x86_64)Compromise is total
BPF verifierkernel_bpf/src/verifier/The load-bearing safety gate; zero unsafe
BPF interpreterkernel_bpf/src/execution/interpreter.rsMust match the verifier’s semantics
JITkernel_bpf/src/execution/jit_aarch64.rsNot enabled in any shipped profile (ADR-0004)
Attach pointsGPIO, PWM, IIO, timer, syscall, scheduler hooksPhysical actuation is the highest-consequence output
BPF mapskernel_bpf/src/maps/Shared state between programs and kernel
Signing trust storekernel_bpf/src/signing/ (Ed25519)One compiled-in production key
Persistent staterootfsNo integrity protection at rest
Control linkshrike_link UART to RP2040Fail-safe state machine on link loss

Adversaries

#AdversaryIn scopeVerdict
A1Malicious BPF author (program bytes fully attacker-chosen)Yes, primaryThe threat the verifier exists for
A2Compromised userspace (arbitrary syscalls)YesSyscall boundary validated; per-process BPF capabilities now gate commands
A3Remote network attackerPartiallyNo NIC driver exists; OTA is out-of-band (SD card / serial)
A4OTA man-in-the-middlePartiallyPrograms are Ed25519-authenticated; the kernel image itself is unsigned
A5Physical access (JTAG, SD swap, side channels)NoA robot in an attacker’s hands is the attacker’s robot
A6Supply chain (malicious dependency)Acknowledged, not defendedSmall no_std dependency tree; no vendoring or cargo vet gate
A7Speculative execution via BPFKnown gapNo Spectre mitigations (#89)

Trust boundaries

  • B1 userspace to kernel: every user pointer/length crosses the bounded UserMemory adapter.
  • B2 BPF load: authenticate, authorize, normalize, verify. Nothing executes unverified.
  • B3 BPF runtime: programs reach the kernel only through helpers whose signatures and argument bounds were checked at verify time.
  • B4 attach: attachment checks the hook context and passes utilization admission.
  • Bootloader: the Limine handoff is trusted and unverified; there is no secure or measured boot.

Mitigation map

AttackPrimary defense
A1 out-of-bounds accessStack bounds and ranged dereference checks for map-value, ctx and packet pointers; per-map value sizes and per-program-type ctx sizes
A1 unbounded executionVerifier recorded-state budget (8,192 states, 64 per pc) plus an interpreter hard instruction limit (100k embedded / 1M cloud)
A1 stack / call-depth abuseProfile stack bound; BPF-to-BPF inlining capped at MAX_CALL_DEPTH = 8 with an expansion size cap
A1 helper contract abusevalidate_helper_call with privilege tier and pointer-argument bounds; helper IDs unified with the runtime table
A1 arithmetic corruptionDivision/modulo-by-zero rejection, uninitialized-register rejection, tnum plus signed/unsigned range tracking
A1 real-time starvationStatic WCET budget at verify time; utilization admission at attach (see Verifier Assurance)
A2 syscall boundarykernel/src/syscall/validation.rs; attach-time GPIO pin and PWM chip/channel validation
A4 program authenticityEd25519 trusted-signer, hash and signature verification; raw instruction loads rejected when enforcement is on
Execution engine integrityInterpreter only in shipped profiles

Gaps

IDGap (as filed)Status on feat/v0.5-runtime
G1Spectre-class speculation unmitigated (#89)Open
G2No privilege check at attach (#176)The normative trust policy now gates trace/scheduler/device attach with per-process BpfCapabilities; init lacks device attach and actuation rights
G3JIT output not independently checked (#177)Moot for shipped profiles (no JIT); remains a precondition in ADR-0004
G4Signature enforcement default-off, no key provisioning (#20)Production builds are signed-only with a build-time key; unsigned needs bpf-unsigned-development. Key provisioning beyond the build-time key is not described
G5No secure / measured boot (#178)Open
G6Dependency supply chain unaudited (#179)Open
G7Kernel image and persistent state unsigned at restOpen

TCB and the seL4 comparison

Measured with wc -l over *.rs (excluding tests/) at f2e38bc:

ComponentLoC
Kernel core (kernel/src)20,756
BPF subsystem (kernel_bpf)26,258
of which verifier7,649 (zero unsafe)
All kernel crates36,564
axiomos TCB (order of magnitude)about 57k LoC Rust

seL4, by contrast, has about 8,700 LoC of C plus about 600 asm with machine-checked functional correctness down to the binary. The repository’s own reading: the axiomos TCB is about six times larger, and it is trusted, not proven. The differentiator is not assurance depth but that untrusted, hot-swappable robotics logic is a first-class kernel object with static safety and timing admission. Formal work is limited to a Lean 4 proof-of-concept for the tnum domain (formal/, #91); see Testing & Verification.

Last updated on