Development

Unsafe And FFI Boundaries

Where ABI and unsafe edges belong

SlopOS is Rust-first. Raw unsafe, naked assembly, linker symbols, and C ABI edges should stay inside the trusted core or inside narrow bridge modules that exist only to connect assembly, bootloader, or linker contracts.

Boundary categories

CategoryBelongs in
Raw CPU and architecture operationsOSTD architecture modules
Naked assembly entry and return pathsOSTD assembly or explicit bridge modules
Linker symbols and link-section declarationsOSTD, which owns every section label and every bracket symbol
Bootloader protocol ABIBoot protocol bridge
Scheduler and interrupt assembly ABIDedicated boundary modules
User pointer validation and raw copiesOSTD user-memory APIs
MMIO, port I/O, DMA, and PCI raw accessOSTD device and memory APIs

The exact allowlist is enforced in the source repo. Public docs describe the policy; the scripts define the current mechanical rule.

Rules

  • Prefer normal Rust functions and typed callback structs.
  • Put raw extern declarations in OSTD, not behind a per-crate wrapper.
  • Register into a linker section with registry_entry!, naming a registry rather than a section string. A crate that could name its own section could name one the linker script's wildcards silently merge into an existing output section, where no post-link check would see it.
  • Do not add ad hoc extern "C" blocks in feature code.
  • A C-ABI symbol whose only caller is Rust does not need C linkage. Route it through a registration hook the way the task-exit and user-task-entry paths do.

Note that these rules are enforced against the expansion, not the source. A macro from another crate can inject unsafe past #![forbid(unsafe_code)] without a diagnostic, so following the rules by hand is not sufficient and not relied on.

  • If an ABI edge needs unsafe, keep the unsafe block small and give it a concrete safety argument.
  • Extend unsafe-check exemptions only with a narrow, documented reason.

Checks

Use targeted rg scans around the code you touched when reviewing a boundary change:

rg 'extern "C"' <changed-subsystem>
rg 'unsafe' <changed-subsystem>
just check-framekernel

The first scans are review aids. The framekernel gate is the policy-enforcing check.

On this page