Skip to main content

Module workdir_fs

Module workdir_fs 

Source
Expand description

Every runtime write, append, create, removal and decision-read inside a capsule’s workdir, performed relative to a held directory descriptor with no symbolic link followed.

The capsule’s shell commands can write anywhere in the accessible workdir, and without --workdir the session directory is that workdir. The runtime itself is unconfined, so a path it builds by joining names onto the workdir and hands to std::fs resolves whatever the capsule planted there: task.md -> ~/victim.txt turns the runtime’s task write into a write to the operator’s file, and tools -> ~/.local/bin turns a tool install into an install outside the capsule. WorkdirRoot is the one way the runtime touches those paths.

§The walk

A relative path is split on /; a segment that is empty, . or .. is refused before any syscall, which also refuses an absolute path. Each directory segment is opened with openat(parent, name, O_DIRECTORY | O_NOFOLLOW) from the descriptor the previous segment produced, starting at the anchor’s own descriptor, so no step resolves a name the capsule could have swapped for a link and no step resolves anything from the anchor’s host path. A segment that fails to open is fstatat(AT_SYMLINK_NOFOLLOW)-ed to say whether it was a link.

This per-component walk is the only implementation, on Linux and macOS alike, for the reason crate::resource_plane keeps one portable resolution path: openat2(RESOLVE_BENEATH) is Linux-only and could only ever be an extra layer over a portable path that has to be correct by itself. Every primitive is rustix’s safe wrapper over the POSIX *at call of the same name.

§Paths in refusals

A WorkdirRefusal names its paths relative to the accessible workdir with the real session id — .murmur/ses_…/plans/plan-1.json, the form peer_file_fetch.stored_path uses — whichever root the call went through. Without --workdir the two roots are the same directory and a session path has no .murmur/<id>/ prefix.

§The refusal latch

Every refusal is also pushed onto a latch every clone of both roots shares. A best-effort writer that swallows its error (a hook log, a blob, MURMUR.md) still leaves the refusal there, and the task loop drains it with WorkdirRoot::take_refusals at its checkpoints and fails the task.

Structs§

WorkdirRefusal
One refused call. path and refused_at are relative to the accessible workdir.
WorkdirRoot
A held directory descriptor inside (or at) the accessible workdir, and the only way the runtime reads its own decisions from, or writes into, that tree.

Enums§

EntryKind
What fstatat(AT_SYMLINK_NOFOLLOW) found at a path’s last component.
RefusalReason
Why a call was refused. The wire names are what workdir_path_refused.reason carries.
WorkdirError
Error from a WorkdirRoot call.
WorkdirOperation
What a refused call was trying to do. The wire names are what workdir_path_refused.operation carries.

Constants§

DEFAULT_DIR_MODE
Mode for a directory created with no reason to choose another: std::fs::create_dir’s, so the umask decides the result exactly as it does for std.
DEFAULT_FILE_MODE
Mode for a file written with no reason to choose another: std::fs::File::create’s, on the same terms as DEFAULT_DIR_MODE.