wasi/fs: per-descriptor directory mutation requires mutate-directory, refuses read-only - #225
Merged
Merged
Conversation
… refuses read-only The #194 residual, resolved on the WIT's side: directory-mutating ops (create/remove-directory-at, unlink-file-at, rename-at and link-at on both ends, symlink-at, set-times-at) now require the mutate-directory flag specifically — write no longer suffices — and refuse with the WIT-mandated read-only code, not bad-descriptor. File-write leaves keep bad-descriptor (WIT-silent; POSIX EBADF) and stop accepting mutate-directory. set-times splits by descriptor kind. open-at now enforces the same doc's escalation clause: a base directory without mutate-directory cannot mint a handle carrying write/mutate-directory or create/truncate/exclusive — previously a {read} directory descriptor could openAt a {write} child, making the per-descriptor layer decorative. Path-ops check kind before permission (not-directory on a file descriptor, wasmtime's Descriptor::dir() ordering). Interop cost is nil in practice: wasi-libc (p2) always requests write|mutate-directory together, and p1-adapter directory descriptors carry neither bit (POSIX dirs open O_RDONLY). Closes #194.
lannbot
enabled auto-merge
August 22, 2026 23:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves the residual left open in #194: which flag authorizes directory mutation on a descriptor, and with what refusal code. Decided by the wasi-filesystem WIT text (identical in the 0.2.x and 0.3 WITs), which turned out to mandate more than the residual asked.
The WIT authority
descriptor-flags.mutate-directory:plus the
open-atdoc paragraph making the handle-escalation rule explicit.Changes (both tracks, shared provider)
mutate-directoryspecifically — the wasi/filesystem: directory-mutating ops never checked descriptor flags #194 residual.writeno longer passes:create-directory-at,remove-directory-at,unlink-file-at,symlink-at,set-times-at, and both ends ofrename-at/link-at.read-only, notbad-descriptor— WIT-mandated (above). The landed choice in the read-only PR predates reading that sentence.open-atenforces the escalation clause: through a base directory lackingmutate-directory, requests forwrite/mutate-directorydescriptor-flags orcreate/truncate/exclusiveopen-flags refuseread-only. Previously a{read}directory descriptor could mint a{write}child, making the per-descriptor layer decorative. (exclusivegoes beyond the WIT's literal create/truncate, mirroring the package-level enumeration; noted in a comment.)writealone and keepbad-descriptor(WIT-silent; POSIX EBADF).mutate-directoryno longer launders file writes ("may only be set on directories").set-timestype-dispatches: directory → mutate-directory/read-only, file → write/bad-descriptor.not-directory(wasmtime parity:Descriptor::dir()→NotDirectory), never a bogusread-only.The package-level grant (
writable, refusingread-onlyfirst on every mutating leaf) is untouched.Interop notes
write|mutate-directorytogether (openat.c), so the tightening costs p2 guests nothing.mutate-directory— but POSIX directory opens areO_RDONLY, so those descriptors carry neither bit and were already refused by the landed check.not-permitted), and itsget-flagsderivesmutate-directoryfrom the open mode.Versioning
No breaking label: the published API surface is unchanged; the observable error-code change (
bad-descriptor→read-onlyon per-descriptor directory refusals) is a spec-conformance fix within 0.x. Relabel at cut time if judged otherwise.Gates
Full
just gatespass (build, test-rust, test-protocol, test-runtime, test-wasi, test-sockets-node, test-ct-runner, test-bundle, test-version-guard, publish-check, test-npm, examples, test-translate, conformance, sched-seeds, shells, browsers, smoke-tls, smoke-c0).Closes #194.