vfsd is the public virtual filesystem daemon for Erix
  • Rust 98%
  • Python 1.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Erik Inkinen fdd7db1a4f
All checks were successful
CI / markdown (push) Successful in 11s
CI / test (push) Successful in 2m22s
chore: Merge native CLI development into main
Merge the selected feature/native-cli history with an explicit two-parent commit so main retains the development lineage and the validated source snapshot. The resulting tree is identical to the selected feature commit; no dependency pins or runtime behavior are changed by this merge.

Previous main: 5f8b41dce4
Selected feature: 6e05c765d1

Publish this integration point following the requested cross-repository merge. Preserve the feature branch and immutable dependency objects for reproducibility; do not squash, rebase or rewrite existing commits.
2026-09-12 08:28:53 +03:00
.github build: Pin dependency and CI helper source commits 2026-09-12 07:44:48 +03:00
scripts fix: Reject unmodelled provider-read stack updates 2026-09-10 03:23:43 +03:00
src fix: Bound provider read-response stack usage 2026-09-10 03:15:19 +03:00
tests fix: Reject unmodelled provider-read stack updates 2026-09-10 03:23:43 +03:00
.editorconfig Initial commit 2026-04-22 04:03:07 +02:00
.gitignore Initial commit 2026-04-22 04:03:07 +02:00
.markdownlint-cli2.yaml Tighten CI markdown policy 2026-05-22 15:10:43 +03:00
ARCHITECTURE.md fix: Reject unmodelled provider-read stack updates 2026-09-10 03:23:43 +03:00
Cargo.toml build: Pin dependency and CI helper source commits 2026-09-12 07:44:48 +03:00
CODE_OF_CONDUCT.md docs: Synchronize shared contribution and review policies 2026-09-12 06:38:23 +03:00
CONTRIBUTING.md build: Pin dependency and CI helper source commits 2026-09-12 07:44:48 +03:00
LICENSE Initial commit 2026-04-22 04:03:07 +02:00
linker.ld fix: keep namespace state below the process stack 2026-07-29 08:39:37 +03:00
README.md fix: Bound provider read-response stack usage 2026-09-10 03:15:19 +03:00
ROADMAP.md fix: Reject unmodelled provider-read stack updates 2026-09-10 03:23:43 +03:00
rustfmt.toml Initial commit 2026-04-22 04:03:07 +02:00
SECURITY.md docs: Synchronize shared contribution and review policies 2026-09-12 06:38:23 +03:00

vfsd

vfsd is the virtual filesystem daemon that owns the EriX filesystem namespace and dispatches capability-scoped sessions to private providers.

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

Running utilities may create an empty regular file through an approved exact entry endpoint and separately acquire content WRITE authority. Explicit file truncation uses only that WRITE endpoint's pinned provider handle, without re-resolving a pathname. Missing internal routes are not reported as missing objects, so they cannot select a utility's missing-destination creation path.

Provider read replies are validated through the existing borrowed wire view, then copied once into the owned backend result, including the complete fixed payload tail. This removes redundant transport-sized stack values without changing request geometry, validation order, provider errors, or capability cleanup. Runtime and smoke PIC builds have an emitted-code read-chain gate below the existing 256 KiB deployment stack, with at least 16 KiB headroom.

This repository implements the EriX virtual filesystem service. Its purpose in EriX is to own the public filesystem namespace while delegating media-specific work to private providers.

Functionally, it routes VFS operations to mounted provider backends and keeps provider authority private. The repository keeps the implementation, interface contracts, tests, and documentation for that behavior in one reviewable ownership boundary.

The maintained responsibilities are:

  • provide rootd's read-write namespace session and loaderd's read-only namespace session on distinct endpoints
  • reserve mount control to rootd's service-control endpoint
  • route mounted paths to private filesystem providers through bounded provider endpoints
  • query trusted filesystem-representable wall time only through one fixed send-only timed endpoint and keep unavailable or synthetic values absent from provider metadata; validated operations forward descriptive V2 values while unavailable time preserves the unchanged V1 provider operation; read-only mounts suppress access-time evidence for namespace, exact-object, and redirection-stream reads so reads remain non-mutating
  • validate endpoint, path, session-owned handle, and operation authority before dispatch
  • authenticate powerbox scopes by endpoint-object equality, resolve selectors inside only that scope, and return operation-bound exact-object endpoints
  • bind create, unlink, rmdir, and rename endpoints to one retained canonical target path; entry calls accept no source selector, and rename accepts only a validated destination basename in the retained source parent
  • bind exact metadata reads and touch updates to the same retained parent and target identity; stat accepts no selector, touch accepts only descriptive access/modification values, and vfsd alone supplies optional trusted ctime evidence after authorization
  • authenticate launchd's transferred executable directory, pin the selected executable provider object, and return a read-only invocation endpoint plus canonical path and metadata evidence
  • resolve launch cwd selectors inside their transferred directory scopes and return provider-pinned, metadata-only directory endpoints whose lifetime is bound to the launched job
  • accept launchd-only installation and idempotent retirement of receive-and-grant, job-bound redirection resolvers in the shared retained-endpoint pool; grant is exercised only by exact stream replies
  • resolve each redirection path only through one transferred exact cwd alias, retain its provider handle, and return disjoint operation and cleanup senders
  • serve direction-limited ordered file reads, writes, closes, and status with one exact shared offset, live-EOF append lookup, and digest-bound release
  • require authority-free startup, client, and provider-reply envelopes and completely retire unwanted capability receipts; only the private powerbox, launch-executable, and installed redirection resolver routes accept their exact documented authority transfers

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

Shell cwd changes use the existing authenticated job resolver with an additive RESOLVE_CWD operation. Each result pins both the selected directory and its original delegated navigation anchor, preserving a separate logical path for cd -L and a physical path for cd -P. Absolute paths and symlink targets never escape that original ceiling; legacy cwd handles retain their old restrictions. Launches and redirections through contextual handles prove live provider identities before effects and keep the complete ancestor chain pinned until completion. A replaced anchor/current directory fails closed, not as a new namespace lookup. Private no-follow component opens and pinned-link reads add no public provider authority; uncertain cleanup stops the service.

Native long listings use an explicit invocation-scoped directory metadata grant independent of enumeration. The receipt-free entry-metadata operation accepts only a validated immediate basename and looks up the child beneath the retained provider directory handle without following links. Exact mount-overlay entries use their retained mount identity and provider root, not an ordinary namespace reopen. Job cwd resolver authority cannot invoke this operation.

Implemented baseline for the VFS service path:

  • public VFS op dispatch for mount, metadata, file I/O, and directory I/O
  • additive namespace dispatch for rename, truncate, symlink/readlink, hard-link request forwarding, and flagged metadata updates
  • provider table setup for selected volatile-memory, EXT, FAT, FAT12, FAT16, and exFAT provider kinds
  • bounded provider RPC transport with in-flight reply polling for slower persistent backend calls
  • post-authorization wall-clock propagation for create, namespace mutation, successful read/write families, metadata changes, redirection I/O, and endpoint-bound exact operations; providers receive values only and never timed or RTC authority. Mount records retain the validated read-only bit so ordinary, exact-object, and redirection-stream reads use unchanged non-mutating provider operations on immutable media instead of attempting an implicit atime update.
  • UTF-8 namespace path/name validation with semantic request bodies: open/create carry validated access flags and other one-path operations do not carry an ignored flag word
  • root-first mount policy
  • synthetic mount-overlay visibility in parent directory reads, with tagged successor cursors that terminate after the final overlay instead of restarting provider enumeration
  • endpoint-derived operation policy and session-owned handle isolation
  • root-only mount control and loaderd read-only discovery authority
  • deployment-configured mount and handle records carved from one exact startup-mapped arena, with no service allocator or compile-time record ceiling
  • provider-pinned exact objects stored in those same deployment records, with a vfsd-only bounded receive-slot interval and no caller-selected handle ID
  • normalized one-capability powerbox scope intake, endpoint-equality authentication, selector digest validation, and receive-only endpoint creation through the narrow startup endpoint factory
  • exact READ_AT, WRITE_AT, READDIR, STAT, TOUCH, MKDIR, UNLINK, RMDIR, and RENAME dispatch bound to the approved operation; one-shot endpoints and provider handles retire after use
  • exact entry mutation grants use one provider-private handle that atomically retains the authenticated parent and target identity or absence; dispatch derives the source basename from retained VFS state and never re-resolves a caller selector
  • exact stat and touch grants use only that opaque provider handle. The public bodies contain no path, mount, namespace, or public handle; touch forwards the vfsd-derived basename and uses V2 only when trusted change-time evidence is available. A proven-absent no-create request consumes no timed query.
  • authenticated broker detachment for installed invocation/job objects: the transferred exact alias selects the record by endpoint equality and is removed without revoking the child-facing receiver or pinned provider handle
  • receipt-free terminal retirement on powerboxd's private route: complete exact lifecycle identity selects the installed grant object only after revocation, then vfsd drops its receiver and closes the pinned provider handle
  • private launch-artifact resolution and release: one transferred directory alias selects either the executable or its derived <executable>.lmf sidecar, and each provider-pinned file remains reachable solely through its own read-only invocation endpoint until authenticated release
  • private launch-directory resolution and release: a cwd selector yields one disjoint READ_METADATA, job-lifetime exact endpoint; authenticated broker release or handle-zero close retires its receiver and provider handle. That same endpoint serves repeatable, receipt-free canonical-path reads for native pwd; no request handle or namespace selector can redirect the query. An exact directory already pinned at / admits rooted launch selectors because their normalized result cannot escape that scope; every narrower exact directory continues to reject rooted selectors
  • launchd-only redirection resolver registration with exactly one RECV|GRANT receipt, exact transaction/session/realm ownership, receipt-free idempotent unregistration, and exhaustive owned-stream teardown; a receipt-free same-realm adoption preflights two exact live resolvers and atomically reparents all remaining source-owned operation, cleanup, and tombstone records before successor teardown
  • cwd-scoped POSIX <, >, >|, >>, and <> opening with selector digest, creation mode, noclobber, direction, and namespace-session enforcement
  • independent operation and cleanup endpoint pairs: operation calls are receipt-free ordered streams; cleanup closes the provider handle before an authority-free digest tombstone acknowledges release retries
  • append EOF lookup remains bound to the originally opened mount even if a later nested mount changes namespace precedence
  • destructive truncate opens the provider handle first so handle-capacity failure cannot lose data; FAT/exFAT synchronize every matching live handle after commit, while ext handles reload committed inode size and block state
  • unit coverage for startup validation, mount-table rules, namespace behavior, extended namespace operations, backend forwarding, resolver receipt cleanup, scoped resolution, disjoint executable/manifest/cwd pinning, job-lifetime close, exact cwd path reads, and exact-object dispatch

The startup rendezvous waits without a daemon-local deadline. The service's fixed role-scoped endpoints and all live retained receivers are scanned nonblocking and cooperatively for fairness. Accepted replies remain retained through transient backpressure. Malformed receipt state, uncertain cleanup, a malformed provider reply, or terminal accepted-call state requests process teardown so namespace/provider authority cannot remain in a quarantined task.

Validation

  • cargo fmt
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test --all-targets --all-features

Dynamic Boot Artifact Evidence

The runtime image contract documents vfsd as a dynamic boot artifact. The image build packages the VFS service daemon 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 root/loader namespace receivers, private provider send endpoints, and one send-only public timed query endpoint. Packaging expands the dedicated VFS state NOBITS range to the page-rounded size derived from the configured mount and handle record counts, then authenticates those counts with the executable. 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. vfsd receives only the documented startup endpoints, peers, and capabilities for its role.

Governance Principles

vfsd governance is scoped to capability-routed namespace sessions and dispatch to private filesystem providers.

The scoped governance rules are:

  • Each caller receives only its dedicated namespace-session endpoint; the startup service endpoint accepts mount control only.
  • Mounts must bind explicit paths, filesystem types, provider endpoints, and block-device identifiers.
  • Provider dispatch must preserve path canonicalization, per-session handle ownership, and endpoint-derived operation bounds. Private-provider calls retain their explicit buffer through authoritative completion without granting callers direct provider authority.
  • Scoped resolution retains neither a namespace alias nor caller-selected path authority: the staged scope is compared to known receive endpoints, dropped before provider resolution, and replaced by one receive-only local endpoint plus a send-only reply alias. Launch-artifact resolution requires nonempty regular files, additionally requires execute permission for the executable, and binds size and canonical path as evidence alongside each exact identity. Rooted launch selectors are accepted only when the transferred exact directory is itself /; a non-root directory scope cannot reinterpret or escape to an absolute path.
  • A redirection resolver is installed only by launchd as a transferred RECV|GRANT endpoint. Each dynamic call must carry one send-only alias of the exact job cwd; vfsd drops that staging alias before any provider call and exercises GRANT only to return direction-limited operation and cleanup senders.
  • Operation endpoints accept no capability receipts and hold the sole provider handle behind one ordered shared offset. Cleanup endpoints accept no receipts, close provider state before replying, and retain only a scrubbed digest tombstone until resolver retirement. A kernel-proven terminal caller is a completed disposition for these receipt-free replies. If the caller retires during a successful resolver reply, the kernel rolls both sender transfers back and vfsd removes the unpublished stream records and all four local endpoint aliases before continuing.
  • Exact-object calls imply the object through the receive endpoint, require a zero public handle field, and permit only the operation recorded at resolution time. A completed receipt-free exact call treats a missing terminal caller as a clean reply disposition, then performs the same one-shot or close retirement; stale calls therefore cannot terminate vfsd or obstruct a later exact cleanup request.
  • Mount and handle exhaustion reflects the explicit deployment record counts, not a crate-wide ceiling. Padding in the mapped arena is not a general allocator and cannot be reused for unrelated authority or state.
  • Filesystem providers stay private and receive no public client authority through vfsd.
  • The wall-clock client can call only vfsd's fixed send-only timed route. It exposes only checked u64 Unix-nanosecond timestamps, returns no value for unavailable or synthetic status, and never passes timed or RTC endpoints to a filesystem provider.

Authority Boundaries

  • vfsd receives only selected provider endpoints explicitly; it must not discover providers through named or ambient lookup.
  • SLOT_VFSD_LOCAL_POWERBOXD_RESOLVER_ENDPOINT_V1, SLOT_VFSD_LOCAL_LAUNCHD_EXECUTABLE_RESOLVER_ENDPOINT_V1, and live registered redirection resolvers are the only authority-bearing request routes. The launch route additionally accepts exactly one RECV|GRANT receipt when installing a resolver; each live resolver accepts exactly one cwd SEND receipt at its fixed staging slot. Powerbox terminal retirement, resolver unregistration, stream operations, and cleanup are receipt-free. Every malformed, extra, or mismatched receipt is retired or the process fails stopped.
  • Rootd's namespace session is read-write but cannot mount. Loaderd's session permits only OPEN, READ_AT, STAT, and CLOSE, rejects write-open flags, and cannot use rootd's handles.
  • New provider types require documented routing and boot-config mount rows before they can be mounted.

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.