Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Plan: POSIX Adapter

Overview

Implementation track for the POSIX adapter sketched in docs/proposals/posix-adapter-proposal.md. The proposal’s Phase P1.1 through P1.3 decomposition is the source of truth; each task below maps to one phase. This plan is ad-hoc until selected.

The v0 phases are parallel-safe with the kernel-core selected milestone in the directories they own (new libcapos/, new libcapos-posix/, new vendor/dns-c-wahern/, new vendor/dash/, new demos/c-hello/, demos/posix-dns-resolver/, demos/posix-pipe-shim/, repo-root system-c-hello.cue, system-posix-dns.cue, system-posix-pipe.cue, matching Makefile targets, and proposal/plan docs). P1.2 and P1.3 add new interfaces under schema/capos.capnp and must serialise on the shared schema serial surface per docs/plans/README.md Concurrency Notes.

P1.1 is the strict prerequisite for P1.2 and P1.3 and is being landed under a separate libcapos C-substrate v0 task; this plan’s Task 1 tracks closeout coordination rather than re-doing the implementation.

Conflict Surface

Owned by this plan:

  • libcapos/ (NEW Rust crate, crate-type = ["staticlib"], standalone like capos-rt/).
  • libcapos-posix/ (NEW Rust crate, same staticlib pattern, links above libcapos).
  • include/capos/ and include/capos/posix/ (NEW C header trees).
  • vendor/dns-c-wahern/ and vendor/dash/ (NEW vendored upstream sources at pinned tags).
  • demos/c-hello/, demos/posix-dns-resolver/, demos/posix-pipe-shim/ (NEW per-phase smoke binaries; demos workspace addition).
  • Makefile (new libcapos-build, libcapos-posix-build, c-build, run-c-hello, run-posix-dns-smoke, run-posix-pipe-smoke, and the successor run-posix-shell-smoke target).
  • Repo-root system-c-hello.cue, system-posix-dns.cue, system-posix-pipe.cue, and the successor system-posix-shell.cue focused-proof manifests.
  • docs/proposals/posix-adapter-proposal.md (status updates, closeout stamps, phase progress).
  • docs/plans/posix-adapter.md (this file).
  • docs/plans/README.md Track Map row only.
  • docs/SUMMARY.md Plans + Proposal Index entries for the new files.
  • book.toml (new proposal entry, enable = false until implementation lands).

Coordinated overlap with sibling tracks:

  • Cargo.toml workspace member entries (or standalone-crate handling) – the new libcapos/ and libcapos-posix/ crates are coordinated with the libcapos C-substrate v0 task that introduces libcapos/. Treat libcapos/ itself as owned by P1.1 until that task closes; this plan owns libcapos-posix/ from P1.2 onwards.
  • schema/capos.capnp (P1.2 adds UdpSocket + NetworkManager.createUdpSocket; P1.3 adds Pipe). Both phases queue on the shared schema/capos.capnp serial surface per docs/plans/README.md Concurrency Notes; do not run concurrently with other schema-touching plans, and do not run P1.2 and P1.3 concurrently against each other.
  • kernel/src/cap/network.rs and kernel/src/virtio.rs (P1.2 UDP path). Coordinate with Device Driver Foundation if that work also touches these files.
  • kernel/src/cap/process_spawner.rs (P1.3 fd-action grant path). Coordinate with anything mutating spawn grants.
  • capos-rt/src/client.rs (P1.2 UdpSocketClient, P1.3 PipeClient).
  • tools/ (new c-build helper if it lands as a standalone tool).

Do not touch from this plan:

  • Kernel-core cap tables, scheduler, device manager, or other userspace runtime files outside capos-rt/src/client.rs extensions described above.
  • tools/remote-session-client/ (owned by remote-session plan).
  • docs/topics.md (auto-regenerated; never edit manually).
  • docs/proposals/userspace-binaries-proposal.md and docs/programming-languages.md (owned by the libcapos C-substrate v0 task that introduces the C library row). Cross-link from this plan only after that task closes, to avoid duplicating the row update.
  • WORKPLAN.md (track-add row update is owned by the planning audit refresh, not by this docs-only lift).

Validation Commands

  • make fmt-check
  • make generated-code-check
  • cargo build --features qemu
  • cargo test-config
  • cargo test-lib
  • cargo build-demos-capos
  • make capos-rt-check
  • make run-smoke
  • Per-phase smoke targets (added as the matching task lands):
    • P1.1: make run-c-hello
    • P1.2: make run-posix-dns-smoke
    • P1.3: make run-posix-pipe-smoke
    • Successor (after Namespace + File caps land): make run-posix-shell-smoke

Treat the matching make run-* target for the most recent phase as required for any iteration that touches this plan’s owned files.

Success Criteria

Each landed phase must keep its make run-* target green, leave unrelated make run-* targets unaffected, and stamp the phase closeout in docs/proposals/posix-adapter-proposal.md with commit hash and minute- precision timestamp. The track is recorded done when the dash port lands green against make run-posix-shell-smoke. P1.2 (DNS resolver smoke) and P1.3 (pipe primitive smoke) close independently as their dependencies land.

Task 1: Phase P1.1 – libcapos C-substrate v0 + C hello-world smoke

  • Owned by the separate libcapos C-substrate v0 task: thin Rust staticlib mirror of capos-rt for C consumers. That task owns libcapos/, include/capos/, the c-build Make helper, demos/c-hello/, and system-c-hello.cue. Tracked here for closeout only – do not duplicate the implementation work in this plan.
  • On merge of the libcapos C-substrate v0 task, stamp the phase closeout in docs/proposals/posix-adapter-proposal.md with commit hash and minute-precision timestamp.
  • On merge of the libcapos C-substrate v0 task, refresh the Track Map row in docs/plans/README.md to reflect that P1.1 is closed and the next schema-touching iteration (P1.2 or P1.3) is the current owner of this plan’s queue position.

Task 2: Phase P1.2 – UDP cap surface + dns.c stub resolver smoke

  • Resolve open question §2 (DNS resolver candidate, recommended dns.c) before vendoring; promote to a final decision in the proposal.
  • Resolve open question §8 (UDP cap surface scope: shape of createUdpSocket, sendTo, recvFrom, close; readiness vs blocking-with-timeout recvFrom) before adding the schema additions; promote to a final decision in the proposal.
  • Resolve open questions §4 (errno representation) and §5 (fd table location) before writing the wrappers; promote each to a final decision in the proposal.
  • Add UdpSocket interface and NetworkManager.createUdpSocket method to schema/capos.capnp. Queue on the shared schema serial surface; do not run concurrently with another schema-touching plan. Run make generated-code-check before downstream Cargo builds.
  • Extend kernel/src/cap/network.rs with the UDP path mirroring the existing TCP path; add UDP RX demux on the existing scheduler-polled smoltcp runtime in kernel/src/virtio.rs.
  • Add typed UdpSocketClient in capos-rt/src/client.rs.
  • Create libcapos-posix/ crate with the minimal socket/sendto/recvfrom/poll surface for one UDP fd at a time, plus malloc/free re-export, errno cell, fd 2 stdio wrapper, clock_gettime/gettimeofday.
  • Vendor dns.c by William Ahern under vendor/dns-c-wahern/ at a pinned tag (single .c plus header).
  • Add demos/posix-dns-resolver/ (new C demo binary).
  • Add system-posix-dns.cue (its own distinct CUE package; imports the shared capos.local/cue/defaults package per the slice-3 defaults pattern).
  • Add make run-posix-dns-smoke target. Smoke must print resolved <name> -> <addr> for a known A record (e.g. against QEMU slirp’s 10.0.2.3) and exit cleanly under QEMU.
  • Stamp the phase closeout in docs/proposals/posix-adapter-proposal.md with commit hash and minute-precision timestamp.

Task 3: Phase P1.3 – Pipe capability + libcapos-posix pipe / fork-for-exec scaffolding

  • Resolve open question §6 (fork policy: whether the shim records inter-call dup2/close as posix_spawn file actions or requires the port to call posix_spawn with explicit file actions) before writing the wrappers; promote to a final decision in the proposal.
  • Resolve open question §9 (pipe cap design: kernel-allocated bounded SPSC ring with EOF on close vs shared MemoryObject + userspace ring) before adding the schema additions; promote to a final decision in the proposal.
  • Add Pipe interface to schema/capos.capnp (small additive change, distinct from UDP and LaunchParameters surfaces). Queue on the shared schema serial surface; do not run concurrently with P1.2 or another schema-touching plan. Run make generated-code-check before downstream Cargo builds.
  • Add kernel/src/cap/pipe.rs: bounded SPSC byte ring backed by a kernel-allocated MemoryObject page, with EOF semantics on close.
  • Extend kernel/src/cap/process_spawner.rs so spawn grants can mint Pipe halves and bind them to the child’s standard fds.
  • Add typed PipeClient in capos-rt/src/client.rs.
  • Extend libcapos-posix/ with pipe/dup2/close over the new cap.
  • Extend libcapos-posix/ with fork/execve/waitpid/ posix_spawn over ProcessSpawner (TLS “next exec is the real spawn” state machine, with the §6-confirmed handling of inter-call file actions).
  • Add demos/posix-pipe-shim/: minimal C program that pipe()s, posix_spawn()s a child whose stdout is the write end, parent reads from the read end and prints. This covers the posix_spawn-direct path.
  • Add a second smoke that exercises the §6-selected fork-for-exec path: if §6 chooses the inter-call recording shim, the smoke must pipe() then fork() then dup2(fd, STDOUT_FILENO) then execve() and prove the recorded file actions are applied to the spawn; if §6 chooses the patched-port variant, the smoke must drive the patched call sequence end-to-end. Either path must fail closed when the recorded action allowlist is violated.
  • Add system-posix-pipe.cue (its own distinct CUE package; imports the shared capos.local/cue/defaults package).
  • Add make run-posix-pipe-smoke target. Smoke must drive both the posix_spawn-direct path and the §6-selected fork-for-exec path, print the child’s emitted line through the parent for each path, and exit cleanly under QEMU.
  • Stamp the phase closeout in the proposal.

Task 4: Successor – vendor dash + ship make run-posix-shell-smoke

  • Blocked on Namespace + File cap surface (Phase 2 of docs/proposals/storage-and-naming-proposal.md). Note the block in the proposal status header until storage proposals land.
  • Vendor dash 0.5.13.x under vendor/dash/ at a pinned tag.
  • Extend libcapos-posix/ with file I/O wrappers over Namespace + File caps (open/read/write/stat/access/unlink, directory iteration via Directory cap), plus getenv/setenv/putenv over the per-process env vector (populated from LaunchParameters if available, else manifest rodata).
  • Add system-posix-shell.cue and make run-posix-shell-smoke target. Smoke must run ls; echo done from a heredoc and print done cleanly under QEMU.
  • Stretch goal: extend the smoke to cat foo | grep bar end-to-end, exercising the P1.3 pipe primitive in a shell pipeline.
  • Resolve open questions §1 (shell candidate, confirm dash) and §7 (fd 0 backing) before vendoring; promote each to a final decision in the proposal.
  • Stamp the phase closeout in the proposal.