- Rust 100%
| .github | ||
| src | ||
| .editorconfig | ||
| .gitignore | ||
| .markdownlint-cli2.yaml | ||
| ARCHITECTURE.md | ||
| Cargo.toml | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| linker.ld | ||
| README.md | ||
| ROADMAP.md | ||
| rustfmt.toml | ||
| SECURITY.md | ||
EriX Root Task (rootd)
rootd is the first user-space policy authority launched by kernel. It
receives the kernel -> root handoff and bootstraps critical early services.
EriX is a clean-room, capability-based microkernel operating system written entirely in Rust.
Technical requirements are tracked in the EriX requirements, conventions, and project documentation.
See:
- docs for design documents, specifications, and development plans.
- Related architecture repositories for kernel, services, libraries, drivers, and integration tooling.
Purpose of This Repository
This repository implements the EriX root userspace coordinator. Its purpose in EriX is to launch the initial service graph and distribute explicit startup authority.
Functionally, it validates boot metadata, starts services in order, transfers capabilities, and performs runtime verification. The repository keeps the implementation, interface contracts, tests, and documentation for that behavior in one reviewable ownership boundary.
The maintained responsibilities are:
- launch the initial service graph in deterministic order
- transfer only the capabilities each service is authorized to receive
- coordinate boot readiness, service startup, and fail-closed authority validation
Clean-Room Policy
EriX follows a strict clean-room philosophy:
- No external source code may be copied.
- No external Rust crates are allowed.
- No code generation tools that embed third-party code.
- All code must be authored within the project.
Violations will result in rejection of the contribution.
License
All EriX repositories are licensed under the ISC License.
Development Model
EriX development is modular, deterministic, reproducible, authority-explicit, security-first, and self-hosting oriented.
This repository follows the project roadmap and the validation rules documented in its own roadmap.
Build Status
Implemented M0 baseline:
no_stdroot task binary with x86_64 SysV entry ABI:rdi = kernel_root_handoff_ptrrsi = kernel_root_handoff_sizerdx = root_endpoint_slot
- strict
kernel -> roothandoff intake validation (lib-handoffparser + descriptor checks) - deterministic rootd status model (
READY,HANDOFF_INVALID,CONTRACT_INVALID,INTERNAL_ERROR,SERVICE_BOOTSTRAP_FAILED) - required
boot-configdiscovery and v1 parse/validate path (ERIXBCFG) - config-driven async dependency startup event loop
- launch dispatch by
launch_kind:- rootd direct service startup
- deviced-managed driver startup (
START_DRIVER)
- feature-gated integration reporting path:
- runtime bootstrap path uses one binary and consumes
boot-configvalidation_profile(nonefor runtime image builds, phase profile IDs for smoke/integration scenario builds) - packaged release runtime builds select
rootd-runtime-release-image; this suppresses rootd stage, service, aggregate, and driver-restamp readiness stamps while preserving the terminalERIX_ROOTD:READYstatus - packaged runtime builds keep
rootd-vfs-verifiersdisabled; local integration profiles opt in when they need late VFS verifier probes and trace markers - compatibility smoke aliases:
rootd-integration-*map to runtime phase features - smoke/integration builds return through
entry.rsfor the final rootdREADYreport so VM harnesses observe completion before the process parks rootd-integration-force-service-failnow trips inside the real post-START_PROCESSstartup handshake so smoke negatives exercise started-child teardown rather than a synthetic final-status rewriterootd-integration-probed-omit-primary-controlandrootd-integration-probed-misroute-primary-controlare integration-only fault hooks for the directrootd -> probedstartup contract; runtime builds do not expose them- force-fail controls remain integration-only:
rootd-integration-smokerootd-integration-force-failrootd-integration-force-service-failrootd-integration-force-spawn-fail
- runtime bootstrap path uses one binary and consumes
Implemented Phase0 orchestration baseline:
- deterministic required module discovery for
memd,vspaced,pagerd,procd, andphase0-probe - deterministic service launch-order state machine:
- intake validated
- module set discovered
- per-service (
memd -> vspaced -> pagerd -> procd) startup-envelope synthesis/validation - probe spawn request contract synthesis/validation
- role-based startup envelope generation using
lib-bootstrap+lib-capabitransfer bundle validation - integration stage progress reporting (
ROOTD_STAGE:*) via feature-gated rootd-report syscall path
Runtime-oriented bring-up path:
- foundation service launch requests issued through kernel-control IPC
(
CREATE_STAGED_PROCESS,REGISTER_PAGER,MAP_FRAME,START_PROCESS) - later service launch requests issued through
procd(CREATE_STAGED_PROCESS, startup-cap install grant materialization, andSTART_STAGED_PROCESS) - pre-bootstrap runtime endpoint inventory validation for the kernel-installed
procddriver endpoint plus the dedicated time, IRQ, hotplug, PCI-config, ACPI-read, console, COM1, i8042, memory, vspace, pager, log, process, and child-populate endpoints - per-service startup envelope delivery and readiness handshake over endpoint
CALL/REPLY - probe spawn request via
procdplus async probe-completion event wait on the dedicated process endpoint before reportingREADY - later foundation launches are issued through
procd's staged lifecycle surface onceprocdis ready - startup transfer synthesis now injects the dedicated
procddriver-lifecycle endpoint intoprocdanddeviced, and extends their caller-visible local slot windows to include slot2112 - startup transfer synthesis now materializes those local driver/control slots as real endpoint-cap aliases before the envelope is delivered, so services no longer rely on canonical-slot reachability to make those assignments real
- startup transfer synthesis now assigns
procdthe dedicated kernel process-control endpoint as its primary control slot and extendsprocd's caller-visible local slot window to include slot2288 - startup transfer synthesis now assigns
devicedthe dedicated kernel log/query endpoint as its primary control slot and extendsdeviced's caller-visible local slot window to include slot2272 - startup transfer synthesis now assigns
timedthe dedicated kernel time-control endpoint as its primary control slot and extendstimed's caller-visible local slot window to include slot2128 - startup transfer synthesis now assigns
irqdthe dedicated kernel IRQ-control endpoint as its primary control slot and extendsirqd's caller-visible local slot window to include slot2144 - startup transfer synthesis now assigns
hotplugdthe dedicated kernel hotplug-control endpoint as its primary control slot and extendshotplugd's caller-visible local slot window to include slot2160 - startup transfer synthesis now assigns
probedthe PCI-config endpoint anddrv-acpithe ACPI-read endpoint as their primary control slots and extends their caller-visible local slot windows to include slots2176and2320 - startup transfer synthesis now assigns
fbcondthe dedicated console/framebuffer endpoint as its primary control slot and extendsfbcond's caller-visible local slot window to include slot2192 - startup transfer synthesis now assigns
drv-serialthe COM1 endpoint anddrv-i8042the i8042 endpoint as their primary control slots and extends those roles' caller-visible local slot windows to include slots2208and2336 - startup transfer synthesis now assigns
memd,vspaced, andpagerdthe dedicated memory, vspace, and pager/fault endpoints as their primary control slot and extends those roles' caller-visible local slot windows to include slots2224,2240, and2256 - startup transfer synthesis now also copies the boot image frame explicitly
into role-local image-frame slots for
procdandpagerdso later spawn and pager map requests do not depend on ambient visibility ofSLOT_BOOT_MODULE_TABLE
Current runtime-mode policy:
- runtime builds are bootstrap-only (no synthetic probe/client/stress execution)
- smoke/integration builds retain synthetic checks for CI verification
- runtime filesystem policy is BootConfig-driven: selected provider entries
supply only the private authority needed by
vfsd, whileMNT1mount rows choose the actual root and secondary mounts phase4-loader-contractsmoke mode reuses the memory-VFS stack and verifies the first typedloaderdABI locally: path-only launch naming, bounded argv/env blocks, deterministic response states, no inherited capability or peer/service endpoint authority, and explicit bootstrap-only static bridge policyphase4-loader-fs-discoverysmoke mode startsloaderdafter the real block-backed filesystem stack, transfers only explicitvfsdandprocdpeers, and verifies public-namespace discovery of executable source paths plus fail-closed missing, directory, malformed, denied, oversized, and changed-while-loading cases. It also exercisesLAUNCH_PATHstatic bootstrap-bridge ELF planning and process handoff, proving a valid disk fixture starts and exits with the expected code while malformed ELF, invalid load-plan, andREQUIRE_DYNAMICrequests fail with typed loader errors.phase4-loader-materialized-launchsmoke mode narrows the mounted-storage verifier to concrete disk-backed executable handoff. It waits forloaderd, requires explicitvfsd/procdpeers, asksloaderdto materialize and launch/data/bin/loader-okand/data/bin/loader-altthroughprocd, and waits for distinct process-completion exit codes before emitting per-file disk-execution proof markers. The same focused verifier launches the changed-source fixture and requires typed stale-source failure with no returned process id before emitting the process-handoff proof marker.phase4-loader-cleanup-authoritysmoke mode reuses the focused block-backed loader stack, injects materialization cleanup faults through integration-only request IDs, and emits per-failure and authority-denial markers after proving disk-launched processes do not inherit provider, block, key, journal, peer-service, loader scratch, or caller authority.phase4-loader-closureis the focused Phase 4.7 final gate. It runs the filesystem-discovery, ELF-plan, materialized-launch, and cleanup-authority scenarios to prove AC11 through AC13 without enabling older broad VM suites.- runtime BootConfig storage-mount proof uses provider-neutral directory/file create, write, read, readdir, unlink, and rmdir operations, so FAT roots are not required to expose POSIX-only extended API semantics
- packaged runtime images keep the service-level readiness surface visible on
fbcond/serial for
fbcond,blockd,ramfsd,keyd,e2fsd,fatd,vfsd, optionalloaderd, and the configuredERIX_DEVICED:READY:*driver set, plus aggregateSTORAGEreadiness when block storage is configured; operation-levelVFS_MOUNTandVFS_IOproof stamps remain late-verifier or focused integration coverage - strict runtime storage bring-up waits for the
drv-virtio-blockendpoint and validates theblockdnamespace plus GPT partitions; the runtime driver readiness tail is restamped through logd's fbcond-only internal path after the configured driver endpoints are present - media-backed filesystem smoke reads fixed representative chunks from the large ext host file, then checks the total size, so targeted filesystem media tests do not spend their budget repeating the same sequential read path
- media-backed ext link-special smoke reads host-created fast/block symlinks, verifies regular-file hard-link counts through create/unlink, and proves FIFO/device metadata cannot be opened as device authority
- media-backed ext rename smoke performs file, symlink, special-metadata,
directory, overwrite, cycle-rejection, and HTree rename checks through public
vfsdcalls - media-backed ext truncate smoke creates
/data/EXTTRUNC.BIN, verifies shrink across block mappings, shrink within the retained tail, zero-filled growth, zero-length shrink, and zero-filled growth from empty through publicvfsdcalls- the integration-only
rootd-integration-phase4-ext-truncatefeature narrows targeted VM runs to this verifier after the realblockd -> vfsd -> e2fsdmount path is established
- the integration-only
- media-backed ext sparse smoke creates
/data/EXTSPARSE.BIN, writes past EOF, verifies zero-filled hole reads and tail data through publicvfsdcalls, then creates/data/EXTSPTRUNC.BINto verify sparse truncate leaves the retained hole zero-filled- the integration-only
rootd-integration-phase4-ext-sparsefeature narrows targeted VM runs to this verifier after the realblockd -> vfsd -> e2fsdmount path is established
- the integration-only
- media-backed ext metadata smoke creates
/data/EXTMETA.TXT, applies explicit mode, owner, atime, mtime, and user filesystem flag updates through publicvfsd, verifies the returned stat fields, sets immutable state, and checks that a later metadata mutation is denied- the integration-only
rootd-integration-phase4-ext-metadatafeature narrows targeted VM runs to this verifier after the real block-backed ext mount path is established
- the integration-only
- media-backed FAT truncate smoke creates
/esp/FATTRUNC.BIN, verifies shrink-across-cluster, shrink-within-cluster, zero-filled growth, zero-length shrink, and zero-filled growth from empty through publicvfsdcalls - media-backed FAT short-name smoke, when the fixture is present, opens and
lists a host-created lowercase 8.3 entry, creates a lowercase 8.3 file through
vfsd, and leaves both for host NT-flag verification- the integration-only
rootd-integration-phase4-fat-short-namefeature narrows targeted VM runs to this FAT short-name verifier after the realblockd -> vfsd -> fatdmount path is established
- the integration-only
- media-backed FAT rename smoke replaces a file and an empty directory through
public
vfsd, checks incompatible replacement denials, and leaves the mutated ESP for hostfsck.fatandmtoolsverification- the integration-only
rootd-integration-phase4-fat-renamefeature narrows targeted VM runs to this verifier after the real block-backed FAT mount path is established
- the integration-only
- media-backed FAT metadata smoke stats host-created FAT timestamps, creates
/esp/FATMETA.TXT, applies explicit atime/mtime/fs_flags updates through publicvfsd, verifies date-only atime, two-second mtime, stat-only creation time, and read-only unlink denial, and leaves the ESP for host checks- the integration-only
rootd-integration-phase4-fat-metadatafeature narrows targeted VM runs to this verifier after the real block-backed FAT mount path is established
- the integration-only
- media-backed exFAT metadata smoke stats host-created primary-entry timestamps,
attributes, 10 ms increments, and UTC offsets, creates
/esp/EXMETA.TXT, applies explicit atime/mtime/fs_flags updates through publicvfsd, verifies read-only unlink denial, and leaves the ESP forfsck.exfat,dump.exfat, and direct metadata checks- the integration-only
rootd-integration-phase4-exfat-metadatafeature narrows targeted VM runs to this verifier after the real block-backed exFAT mount path is established
- the integration-only
- media-backed encrypted casefold ext smoke verifies fscrypt v2 lookup and
readdir through public
vfsdcalls when/data/secureis present, while keeping all key material private to thekeyd/e2fsdprovider path - volatile VFS smoke now extends the basic file/directory pipeline with rename,
truncate, symlink/readlink, hard-link rejection, and metadata-update checks
through the public
vfsdendpoint - fsverity media uses a dedicated boot-config validation profile that mounts the
same private
keyd/e2fsd/fatd/vfsdstack and verifies only the verity-protected ext marker through public VFS reads - read-only-only ext4 feature media uses a dedicated boot-config validation
profile that mounts
/datawith the VFS read-only flag and verifies host marker plus HTree traversal without creating mutation handles - runtime-only builds keep the non-returning ready-terminal handoff after
bootstrap completes; smoke/integration builds do not divert there and rely on
entry.rsto publish the terminalREADYstatus phase3-framebufferbootstrap fails closed ifconsole-fontis not presentphase3-framebufferverification now budgets enough fbcond read chunks to scan the full retained continuity window instead of assuming the whole stream fits inside the old 256-read limit- rootd now treats the first
ERIX_ROOTD:READY:FBCONDcursor capture as best-effort: if fbcond is still re-entering its service loop, later framebuffer verification falls back to retained-stream cursor0instead of failing bootstrap immediately on that handoff race, and each timed retry rescans from fbcond's current oldest retained byte instead of advancing from a non-absolute offset derived from cursor0 phase3-inputbootstrap requiresdrv-i8042,drv-ps2-kbd,drv-ps2-mouse, andinputd
Authority cleanup status:
- runtime launch now always sheds legacy untyped plus kernel/device-management
caps after successful
devicedhandoff devicedreceives the log/query endpoint plus the narrowCHILD_POPULATEendpoint, not the broad process endpointrootdrejects any populated legacy slot4during runtime endpoint inventory validation instead of tolerating bootstrap compatibility aliasesCAP_COPY (8)is treated as reserved/denied in transport routing; onlyCAP_COPY_ATTENUATEDremains available on the narrow child-populate path- post-start bootstrap failures now fail closed: once
START_PROCESSsucceeds, any later startup or immediate finalize failure kills the child with managed-stop, waits for its terminal event, destroys the process, and drops the retained local service endpoint slot before reportingSERVICE_BOOTSTRAP_FAILED - startup-wired peers are expected to validate their delegated local slots
directly; unused
namedstartup caps are being removed
Governance Principles
rootd governance is scoped to deterministic service launch and explicit
capability transfer.
The scoped governance rules are:
- It launches services only from validated boot configuration and known startup contracts.
- It transfers no capability unless the target role is authorized to receive that exact authority.
- It keeps startup ordering explicit so dependent services cannot race authority setup.
- It treats residual, ambient, or duplicate authority as a startup validation failure.
Authority Boundaries
rootdowns initial distribution of service capabilities but does not make later service policy decisions.- New services must be represented through bounded boot-config metadata and documented transfer rules.
Contact
Development occurs in EriX organization and discussions happen in issues and design documents.
No decisions are considered valid without documented rationale.
Maintainers can be reached via email: admin@erikinkinen.fi.