loaderd is the native program-loader service for EriX
  • Rust 99.9%
  • Linker Script 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Erik Inkinen 096f3deda8
All checks were successful
CI / markdown (push) Successful in 5s
CI / test (push) Successful in 33s
Merge branch 'feature/dynlink'
2026-07-23 15:11:05 +03:00
.github Use branch-aware cargo overrides in CI 2026-06-23 18:31:40 +03:00
src loaderd: stabilize dynamic launch scratch buffers 2026-05-29 09:51:35 +03:00
.editorconfig Initial commit 2026-05-22 15:17:29 +02:00
.gitignore Initial commit 2026-05-22 15:17:29 +02:00
.markdownlint-cli2.yaml Initial commit 2026-05-22 15:17:29 +02:00
ARCHITECTURE.md loaderd: stabilize dynamic launch scratch buffers 2026-05-29 09:51:35 +03:00
Cargo.toml Validate static ELF load plans 2026-05-22 18:22:52 +03:00
CODE_OF_CONDUCT.md Initial commit 2026-05-22 15:17:29 +02:00
CONTRIBUTING.md Initial commit 2026-05-22 15:17:29 +02:00
LICENSE Initial commit 2026-05-22 15:17:29 +02:00
linker.ld Add loaderd filesystem discovery service 2026-05-22 17:54:02 +03:00
README.md loaderd: stabilize dynamic launch scratch buffers 2026-05-29 09:51:35 +03:00
ROADMAP.md loaderd: stabilize dynamic launch scratch buffers 2026-05-29 09:51:35 +03:00
rustfmt.toml Initial commit 2026-05-22 15:17:29 +02:00
SECURITY.md Initial commit 2026-05-22 15:17:29 +02:00

EriX Program Loader (loaderd)

loaderd is the native program-loader service for EriX. It is a no-std service binary that receives only an explicit service endpoint, send-only vfsd and procd peers, and an optional send-only dynlinkd peer for Phase 5.4 dynamic launch planning.

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 program-loader daemon. Its purpose in EriX is to validate executable sources, route static and dynamic native ELF sources through the correct policy path, transfer validated filesystem bytes to procd, and hand materialized launch results back to callers.

Functionally, it accepts loader IPC requests, resolves executable paths through the public VFS namespace, reads file contents through vfsd, validates source metadata, validates static ELF segment layout through lib-elf, validates native ET_DYN launch metadata for Phase 5.4, calls dynlinkd for dynamic object planning, and returns deterministic success or failure responses after calling procd for accepted launches. The repository keeps the implementation, interface contracts, tests, and documentation for that behavior in one reviewable ownership boundary.

The maintained responsibilities are:

  • validate its startup envelope and explicit vfsd/procd peers
  • resolve canonical absolute UTF-8 VFS paths through public vfsd calls
  • reject malformed, missing, directory, empty, oversized, read-denied, and changed-while-loading executable sources
  • build deterministic static ELF load-plan summaries without allocator authority
  • provide a target-only no-heap global allocator so dependency crates that expose alloc-backed APIs can link in dynamic artifact builds without granting runtime heap authority
  • reserve explicit target stack space and encode loader-image chunks directly into the IPC transfer buffer, avoiding duplicate large stack-resident chunk copies during materialized handoff
  • detect static ET_EXEC versus dynamic ET_DYN executable sources and reject policy mismatches before process handoff
  • send manifest-bounded dynamic object metadata to dynlinkd over the explicit Phase 5.4 startup peer
  • transfer validated file-backed executable bytes and segment metadata to procd through the ordered materialization ABI
  • expose malformed ELF, invalid load-plan, unsupported dynamic-policy, and process-handoff failures through typed loader responses
  • request process creation only through the typed procd begin/chunk/commit materialization handoff
  • preserve the non-delegating Phase 4.7 loader authority policy

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.

Status

Implemented baseline:

  • no-std loaderd service entry and startup handshake
  • SERVICE_ROLE_LOADERD startup validation with no primary control endpoint
  • explicit send-only vfsd startup peer at SLOT_LOADERD_LOCAL_VFSD_ENDPOINT_V1
  • explicit send-only procd startup peer at SLOT_LOADERD_LOCAL_PROCD_ENDPOINT_V1
  • optional send-only dynlinkd startup peer at SLOT_LOADERD_LOCAL_DYNLINKD_ENDPOINT_V1
  • DISCOVER_PATH IPC handling through lib-vfs client helpers
  • canonical path, file-type, empty-file, size-limit, execute-bit, and stable metadata checks before reporting a discovered executable
  • LAUNCH_PATH static-bootstrap-bridge validation through lib-elf
  • target x86_64-unknown-none builds install a no-heap global allocator that always fails allocation; loader plans continue to use caller-provided bounded scratch buffers and fixed segment arrays
  • deterministic empty argv/env startup state for the static bridge; non-empty argument or environment blocks fail closed until a startup-envelope delivery ABI exists
  • malformed ELF and invalid segment-layout rejection before process mutation
  • REQUIRE_DYNAMIC launch handling for native ET_DYN files with inline dynamic tables, SysV hash, symbol and relocation metadata, and typed dynlinkd resolve-object planning before process handoff
  • deterministic rejection of non-bootloader static ET_EXEC sources unless the caller explicitly selects the retained static bootstrap/test-fixture bridge
  • deterministic procd materialized process handoff after a valid static plan, returning process id, entry point, and launch id on success
  • Phase 4.7.6 materialization model: loaderd retains executable bytes only in bounded local scratch until an ordered inline transfer completes; procd owns frame allocation, segment copy, zero-fill, permission sealing, address-space mapping, and cleanup
  • Phase 4.7.7 transfer ABI: lib-ipc now defines begin/chunk/commit loaderd -> procd materialization bodies with bounded source identity, source/plan hashes, segment metadata, ordered chunk ranges, and executable or dynamic-object image kind
  • Phase 4.7.8 materialized launch: LAUNCH_PATH now sends source bytes and segment metadata through the transfer ABI, receives a procd launch id, and proves the old summary-only handoff is not the filesystem execution path
  • Phase 4.7.10 cleanup hardening clears executable scratch after source read, close, final-stat, ELF-plan, and process-handoff failures, and also drops the scratch buffer after successful handoff so executable bytes do not remain in loaderd state
  • Phase 5.4.5 dynamic loader integration is validated by the focused phase5-dynlink-loader scenario, which proves disk-backed dynamic launch, static runtime rejection, retained static fixture handling, and dynlink failure cleanup without adding loader authority
  • Phase 5.4.12 dynamic materialization now appends the manifest-selected dependency object bytes to the executable transfer, validates relocation targets against writable non-executable file-backed ranges, applies supported relocations before handoff, and proves the launched process uses dependency object data rather than boot-image or summary-only bytes
  • Phase 5.4.15 dynamic cleanup clears the full dynamic materialization scratch region after object discovery, graph, object-load, relocation, or handoff failures, keeps dependency objects per-process-private in the current model, and preserves the explicit static fixture bridge after injected dynamic cleanup faults
  • Runtime peer calls use a bounded service-call budget sized for block-backed VFS dependency metadata and read operations during dynamic materialization; this changes only wait behavior and does not add provider, block, process, or memory authority.
  • Phase 5.4.32 boots loaderd itself as a signed dynamic artifact in the focused Phase 4 service-port gate. Target builds reserve a 128 KiB .bss.stack_reserve region, copy incoming launch requests into a fixed request scratch buffer before nested VFS/dynlink/procd calls, and send each procd image chunk from one encoded transfer buffer, preserving the no-heap and peer-only authority model.
  • Phase 4.7 closure is validated by the focused phase4-loader-closure scenario group, which proves VFS policy rejection, malformed ELF rejection, true filesystem-byte execution, stale-source rejection, cleanup, and authority denial without granting extra loader authority
  • unit tests for startup, discovery, dispatch, and load-plan contracts

Dynamic Boot Artifact Evidence

Phase 5.4.37 documents loaderd as a dynamic boot artifact. The image build packages the program loader service as an ELF64 x86_64 ET_DYN executable with .erix_dynlink metadata in the signed dynlink-store and mirrors it under /lib/erix/dynlink with its required shared objects.

Startup remains rootd through procd staged dynamic creation before dynlinkd; authority remains explicit VFS, procd, and later dynlinkd peers. Dynamic packaging and filesystem mirror records are evidence and launch inputs only; they do not grant filesystem, loader, object-store, service-discovery, provider-bypass, block-device, or dynlinkd authority. loaderd receives only the documented startup endpoints, peers, and capabilities for its role.

Governance Principles

loaderd governance is scoped to executable source validation and future load plan construction.

The scoped governance rules are:

  • It must use explicit startup authority; no ambient VFS, provider, block, key, journal, or peer-service authority is allowed.
  • It must read executable bytes only through vfsd, so mounted-provider policy remains authoritative.
  • It must fail closed before process mutation unless dynamic metadata is accepted by dynlinkd when required and procd accepts the typed handoff.
  • Filesystem-backed execution must transfer validated bytes and segment metadata explicitly to procd; the legacy summary-only handoff is denied and cannot satisfy disk-execution proof.
  • Dependencies in Cargo.toml track the main branch; integration tooling supplies local branch overrides for multi-repo validation.

Policy Boundaries

  • loaderd does not own process lifecycle; procd remains responsible for process objects, address-space creation, startup, event tracking, and cleanup.
  • loaderd does not own address-space or paging policy; vspaced and pagerd retain those responsibilities.
  • loaderd does not bypass vfsd or private filesystem providers.
  • loaderd does not receive memory, VSPACE, install-grant, or process-control authority for materialization; it can only send bounded launch data through the explicit procd peer and dynamic-link metadata through the explicit dynlinkd peer.

Contact

Development occurs in EriX organization and discussions happen in issues and design documents.

Discussions should occur via issues or design documents.

No decisions are considered valid without documented rationale.

You can also reach out to maintainers via email: admin@erikinkinen.fi.