procd is the user-space process lifecycle manager. It is responsible for controlled process/task creation and lifecycle policy.
  • Rust 98.5%
  • Linker Script 1.5%
Find a file
Erik Inkinen adaca91fef
All checks were successful
CI / markdown (push) Successful in 4s
CI / test (push) Successful in 22s
Document Phase 4.7 materialization closure
2026-05-23 01:45:52 +03:00
.github Tighten CI markdown policy 2026-05-22 15:10:37 +03:00
src Add loader cleanup fault coverage 2026-05-23 01:36:55 +03:00
.editorconfig Initial commit 2026-02-26 17:48:05 +01:00
.gitignore Ignore local .ci workspace 2026-04-15 21:53:01 +03:00
.markdownlint-cli2.yaml Tighten CI markdown policy 2026-05-22 15:10:37 +03:00
ARCHITECTURE.md Document Phase 4.7 materialization closure 2026-05-23 01:45:52 +03:00
Cargo.toml Add loader cleanup fault coverage 2026-05-23 01:36:55 +03:00
CODE_OF_CONDUCT.md Tighten CI markdown policy 2026-05-22 15:10:37 +03:00
CONTRIBUTING.md Tighten CI markdown policy 2026-05-22 15:10:37 +03:00
LICENSE Initial commit 2026-02-26 17:48:05 +01:00
linker-phase0-exit.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
linker-phase0-fault-kill.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
linker-phase0-isolation-a.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
linker-phase0-isolation-b.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
linker-phase0-probe.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
linker-phase1-lookup-client.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
linker-phase1-time-client.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
linker-phase2-irq-client.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
linker.ld Keep startup stacks in loaded image reserve 2026-05-23 00:23:00 +03:00
README.md Document Phase 4.7 materialization closure 2026-05-23 01:45:52 +03:00
ROADMAP.md Document Phase 4.7 materialization closure 2026-05-23 01:45:52 +03:00
rustfmt.toml procd: drop unstable rustfmt options for stable toolchains 2026-03-23 10:19:56 +02:00
SECURITY.md Tighten CI markdown policy 2026-05-22 15:10:37 +03:00

EriX Process Manager (procd)

procd is the user-space process lifecycle manager. It is responsible for controlled process/task creation and lifecycle policy.

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 proc service daemon. Its purpose in EriX is to provide the proc service role through explicit IPC and startup authority.

Functionally, it implements the daemon runtime, state model, IPC handling, and validation tests. The repository keeps the implementation, interface contracts, tests, and documentation for that behavior in one reviewable ownership boundary.

The maintained responsibilities are:

  • implement the proc service runtime and state model
  • validate startup authority before accepting IPC requests
  • handle bounded service operations through the assigned endpoint set
  • keep service behavior, tests, and authority invariants documented

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.

Implementation Status

Runtime baseline:

  • no_std executable service binary (x86_64-unknown-none) with SysV entry ABI
  • startup envelope parsing/validation via lib-bootstrap
  • role/intake contract validation via lib-capabi
  • runtime IPC server loop (RECV + REPLY) for lifecycle request handling
  • staged lifecycle path wired through kernel-control IPC: CREATE_STAGED_PROCESS, START_PROCESS, and ABORT_STAGED_PROCESS
  • compatibility SPAWN_SERVICE and extension/test SPAWN requests are now translated onto the same staged child create/start path instead of using a separate direct CREATE_PROCESS flow
  • extension/test helper binaries now follow the same canonical .text.service_entry trampoline convention as ordinary service images so staged child start uses the validated ELF entry surface consistently
  • extension/test helper binaries that do deeper IPC/interrupt call chains also reserve explicit in-image stack space in their per-bin linker scripts so the staged spawn stack does not collapse back into image data
  • typed service spawn compatibility path: IPC_PHASE0_PROCD_OP_SPAWN_SERVICE (0x402)
  • typed staged lifecycle paths:
    • IPC_PHASE0_PROCD_OP_CREATE_STAGED_PROCESS (0x405)
    • IPC_PHASE0_PROCD_OP_START_STAGED_PROCESS (0x406)
    • IPC_PHASE0_PROCD_OP_ABORT_STAGED_PROCESS (0x407)
  • legacy generic Phase0SpawnRequestV1 is now reserved for extension/test roles (role >= SERVICE_ROLE_EXTENSION_BASE) and is rejected for declared service roles
  • ERIX_KERNEL:PROCD_DEBUG:* boot reports are smoke-only, so appliance dev/release images do not pick up lifecycle trace noise during normal bring-up
  • typed lifecycle control paths:
    • IPC_PHASE0_PROCD_OP_STOP_PROCESS (0x404)
    • IPC_PHASE0_PROCD_OP_WAIT_PROCESS_EVENT (0x408)
    • IPC_PHASE0_PROCD_OP_QUERY_PROCESS (0x409)
    • IPC_PHASE0_PROCD_OP_SET_RESTART_POLICY (0x40A)
    • IPC_PHASE0_PROCD_OP_GET_RESTART_POLICY (0x40B)
    • IPC_PHASE0_PROCD_OP_UPDATE_FOUNDATION_ENDPOINTS (0x40C)
    • IPC_PHASE0_PROCD_OP_LAUNCH_LOADED_IMAGE (0x40D) retained as a reserved/denied legacy summary handoff
    • IPC_PHASE0_PROCD_OP_BEGIN_LOADER_IMAGE_TRANSFER (0x40E), IPC_PHASE0_PROCD_OP_SEND_LOADER_IMAGE_CHUNK (0x40F), and IPC_PHASE0_PROCD_OP_COMMIT_LOADER_IMAGE_TRANSFER (0x410) for the materialized loaderd static-bootstrap handoff
    • IPC_PHASE0_PROCD_OP_ADOPT_PROCESS (0x403) retained only as a reserved/denied ABI id
  • dedicated driver-lifecycle endpoint installed at SLOT_PROCD_DRIVER_ENDPOINT (2112) and validated during startup
  • primary local kernel-control slot is now the dedicated SLOT_KERNEL_PROCESS_ENDPOINT (2288), which bounds procd to the process/capability lifecycle ops it actually uses
  • procd no longer receives local CNODE, TCB, or VSPACE management copies in its startup intake; routine lifecycle work is driven by its explicit process-control endpoint, staged child replies, and install grants
  • deviced spawns receive an extended caller-local slot window so the dedicated procd driver-lifecycle endpoint at 2112 and deviced's dedicated kernel log/query primary control slot at SLOT_KERNEL_LOG_ENDPOINT (2272) both stay visible when rootd assigns them
  • timed spawns receive an extended caller-local slot window so the dedicated kernel time-control endpoint at SLOT_KERNEL_TIME_ENDPOINT (2128) stays visible when rootd assigns it as the primary control slot
  • irqd spawns receive an extended caller-local slot window so the dedicated kernel IRQ-control endpoint at SLOT_KERNEL_IRQ_ENDPOINT (2144) stays visible when rootd assigns it as the primary control slot
  • hotplugd spawns receive an extended caller-local slot window so the dedicated kernel hotplug-control endpoint at SLOT_KERNEL_HOTPLUG_ENDPOINT (2160) stays visible when rootd assigns it as the primary control slot
  • probed, drv-acpi, drv-serial, and drv-i8042 spawns receive extended caller-local slot windows so their dedicated narrow PCI-config, ACPI-read, COM1, and i8042 primary-control endpoints stay visible when the parent assigns them
  • fbcond spawns receive an extended caller-local slot window so the dedicated console/framebuffer endpoint at SLOT_KERNEL_CONSOLE_ENDPOINT (2192) stays visible when rootd assigns it as the primary control slot
  • memd, vspaced, and pagerd spawns receive extended caller-local slot windows so the dedicated memory, vspace, and pager/fault endpoints at SLOT_KERNEL_MEM_ENDPOINT (2224), SLOT_KERNEL_VSPACE_ENDPOINT (2240), and SLOT_KERNEL_PAGER_ENDPOINT (2256) stay visible when rootd assigns them as the primary control slot
  • filesystem provider work filesystem provider, key-service, and loader-service spawns receive a caller-local slot window sized through loaderd, so e2fsd, fatd, the private keyd service, and loaderd can receive only their explicit role-local endpoint slots without inheriting ambient service or driver authority
  • startup ready-state now uses caller-local QUERY_LOCAL_CAP on bare metal, with QUERY_CAP retained for host/test scaffolding, to validate the actual local control slot, service endpoint slot, and every declared transferred slot
  • those local control and driver-lifecycle slots are now real copied endpoint aliases materialized by rootd, not just documented slot conventions
  • deterministic process-id/endpoint assignment from kernel-control responses
  • async probe-completion notify path for bootstrap completion signaling
  • rootd now directly launches only procd; once procd is ready it stages and starts later foundation and runtime services itself
  • ADOPT_PROCESS is no longer a live runtime bridge; the op id is retained only as a reserved/denied ABI slot for compatibility
  • runtime endpoint policy is now split by local endpoint:
    • bootstrap/service endpoint accepts only non-drv-* spawns and stops
    • dedicated driver endpoint accepts only drv-* lifecycle requests
    • the driver endpoint sees only drv-* wait/query/restart-policy traffic
  • once foundation endpoints are installed, procd keeps a short-timeout blocking receive on the bootstrap endpoint and re-polls the driver endpoint between timeouts so later deviced driver spawns cannot be stranded behind bootstrap-only receive state
  • bootstrap-only foundation endpoint updates are published through UPDATE_FOUNDATION_ENDPOINTS so procd can start with pagerd = 0 and bind those slots later without reviving the old adoption path
  • spawn requests now consume an explicit procd-local image-frame slot instead of assuming the canonical boot-module-table slot is still visible in the child CSpace
  • legacy loader summary handoff requests through LAUNCH_LOADED_IMAGE (0x40D) are denied before mutation so they cannot pass as filesystem-backed execution
  • loader materialization requests from loaderd are accepted only on the bootstrap endpoint and lowered onto the existing staged child path; the transfer carries ordered validated bytes and segment metadata, not caller-selected frame, VSPACE, memory, install-grant, service, or peer authority
  • Phase 4.7.8 filesystem-byte execution is a procd-owned transaction: loaderd supplies ordered validated bytes and segment metadata, while procd owns frame allocation, segment copy, zero-fill, child address-space mapping, start, event tracking, and cleanup
  • Phase 4.7.10 cleanup regression coverage now injects materialization failures after transfer, child creation, frame allocation, partial mapping, partial segment copy, and event registration, then proves process, endpoint, VSPACE, frame, memory-write, and managed-process state is accounted for after cleanup
  • Phase 4.7 closure evidence comes from the focused loader scenario groups: filesystem discovery, ELF-plan rejection, materialized disk-byte execution, stale-source rejection, cleanup, and authority denial all run without the older broad VM matrix
  • the current static bridge starts with deterministic empty argv/env and no stream startup envelope; non-empty startup delivery remains a later runtime ABI slice
  • spawned service images now keep any declared .stack_reserve region in a final loaded segment so stack_top = module.vaddr_end lands in explicit reserved stack space after live .data/.bss
  • every staged syscall helper (phase0-probe, phase1-lookup-client, phase1-time-client, and phase2-irq-client) now declares a 64 KiB .stack_reserve so the first user-mode syscall frame cannot underflow into adjacent writable image state
  • staged extension helper binaries now keep the canonical .text.service_entry wrapper so procd launches the intended helper entry instead of falling through to a null start address
  • staged create replies now return a caller-local child endpoint alias plus a kernel-issued install grant, so callers populate the child's private CSpace before procd requests start
  • managed stop uses kernel KILL_PROCESS plus synchronous event retirement
  • foundation-service startup is non-blocking before discovery comes online: procd boots without requiring named/logd/crashd availability
  • Late-bound logd and crashd peers are authority only after named rematerializes them into their canonical local slots with the expected role; transport failures clear the cached slot and drop the local cap before retry.

Validation Note

The host/test QUERY_CAP fallback remains cfg-scoped so runtime/release builds stay warning-free.

Governance Principles

procd governance is scoped to process/service creation and driver lifecycle execution.

The scoped governance rules are:

  • It starts services and drivers only from explicit launch requests and assigned capabilities.
  • It must not infer device ownership; driver authority comes from deviced policy.
  • It preserves process identity, startup metadata, and failure reporting for callers.
  • It treats residual launch authority or malformed start envelopes as validation failures.
  • It must not acquire filesystem/provider authority to launch disk programs; file-backed executable bytes arrive only through an explicit loaderd transfer contract.

Authority Boundaries

  • procd operates only through startup-assigned service capabilities.
  • New authority must be represented in bootstrap/capability validation and integration tests before use.
  • Materialized loader launches must not accept caller-selected frame slots, VSPACE caps, install grants, service endpoints, or peer endpoints from loaderd; those remain procd-owned or launch-policy-owned surfaces.
  • Loader cleanup fault hooks are integration/test-only and do not grant loaderd provider, block, key, journal, peer-service, scratch, or caller-inherited authority.

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.