Skip to content

Fuzzing coverage gap: generative testing of per-preopen FsPerms enforcement #14103

Description

@4ktLuffy

Feature

WASI doesn't appear to be exercised by any fuzz target. The OSS-Fuzz crates/ coverage report for 2026-08-09 lists 15 instrumented crates — cache, cli-flags, component-util, core, cranelift, environ, fiber, fuzzing, jit-debug, jit-icache-coherence, test-util, unwinder, wasmtime, wast, winch — and no wasi* crate is among them. Grepping fuzz/fuzz_targets/ and crates/fuzzing/src/ for wasi also returns nothing.

Would a generative, stateful fuzz target for per-preopen FsPerms enforcement be useful? I'd rather ask than build, partly because there may be good reasons this hasn't been done that aren't visible from outside.

Benefit

Filesystem permissions look like they're enforced at three levels, and generative coverage seems to exist for the outer two but not the middle one:

Layer Mechanism Generative coverage
WASIp1 rights spec-level, per-fd wasi-testsuite — fixed conformance cases (e.g. truncation_rights.rs)
wasmtime FsPerms embedder-level, per-preopen none found
cap-std containment per-Dir handle cap-std's fuzz_targets/cap-primitives.rs, with cfg(racy_asserts) checks

The three recent WASI advisories all sit in that middle layer:

Advisory Fix Cause
GHSA-2r75-cxrj-cmph (High) dc740c909 TRUNCATE didn't set open_mode |= OpenMode::WRITE, so the perms check saw a read-only open
GHSA-4ch3-9j33-3pmj (Moderate) 2dc3f443d link_at/rename_at checked directory mutability but not permission parity
GHSA-3p27-qvp9-27qf (Low) f069f125c WASIp1 fd_renumber descriptor-table handling

In each the permission gate runs in crates/wasi/src/filesystem.rs before cap_primitives is called, so cap-std's fuzzer isn't positioned to catch them — and FsPerms has no cap-std analogue to test against. The regression tests added with those fixes (p{1,2,3}_file_truncation_readonly.rs, p{1,2,3}_file_{hardlink,rename}_across_perms.rs) are targeted cases rather than generated sequences.

Implementation

Sketch, open to redirection:

  • Two or more preopens with differing FsPerms — the link/rename case needs at least two.
  • Random sequences of filesystem operations across them, spanning the preopen boundary.
  • Oracle: with a ReadOnly preopen, snapshot the tree before and after and assert it's unchanged. That follows the documented contract on FsPerms directly and needs no model of individual operation semantics — it wouldn't need to know open_at(TRUNCATE) should fail, only that a file got shorter. atime excluded, since reading metadata is permitted.
  • A second oracle asserting host file descriptors return to baseline would cover the fd_renumber class.
  • p1, p2 and p3 separately, since the regression tests suggest fixes don't automatically carry across surfaces.

Before proposing any of it as a PR I'd calibrate: check out the commit before each of the three fixes and confirm the oracle fires, then confirm it's silent across wasi-testsuite and crates/wasi/tests/. If it can't detect the three bugs already known, it isn't worth reviewing.

Alternatives

Extend the hand-written tests instead. FsPerms has two states, so the space is arguably small enough to enumerate — which is roughly what the current regression tests do. My hesitation is that the real space is operations × 2 permission states × 2+ preopens × path shapes × symlink/hard-link states × 3 API surfaces, and the link/rename issue was a relational property across two guest-chosen descriptors. But it's a fair objection and I'd rather hear it now than after writing the harness.

Fuzz at the cap-std layer. Doesn't reach it — FsPerms doesn't exist there.

Do nothing. Entirely possible this is deliberate; filesystem fuzzing is slow and awkward under OSS-Fuzz. If so, knowing that is worth the issue, and it may be worth a line in fuzz/README.md so the next person doesn't retrace it.


Happy to take this to an RFC instead if that's a better fit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    fuzzingIssues related to our fuzzing infrastructurewasi:implIssues pertaining to WASI implementation in Wasmtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions