host vfs: synthesize POSIX permission bits for host mounts on Windows#965
Open
mho22 wants to merge 2 commits into
Open
host vfs: synthesize POSIX permission bits for host mounts on Windows#965mho22 wants to merge 2 commits into
mho22 wants to merge 2 commits into
Conversation
Windows has no POSIX permission model. Node's `fs.statSync` reports every
host entry as `0o666` (writable) or `0o444` (read-only), with no
owner/group/other split, no execute/search bit on directories, and `chmod`
cannot express POSIX bits. Two things then break for a guest process that
drops privileges (e.g. a php-fpm worker running as a non-root uid):
- Directory lookup enforces `X_OK` on every path component, so with no
search bit the worker cannot traverse any host-backed directory — the
whole mounted tree is untraversable and every request fails.
- The worker must also write into the mount (WordPress writes its SQLite
database, uploads, and cache under the mounted tree). Hosts grant this
by `chmod`-ing those directories world-writable, a no-op on Windows
that also never reaches this overlay, so the intent is invisible here.
This is a host-platform boundary, not a POSIX gap in the kernel: Windows
ACLs don't map to POSIX bits, so the kernel can't enforce them anyway. When
the native mode carries no meaningful permission bits (Windows only), the
NativeMetadataOverlay now represents host-backed entries as world-accessible
— `0o777` directories, `0o666` files — so a privilege-dropped guest can both
traverse and write the sandbox it was given, while still honoring the one
attribute Windows exposes by mapping read-only entries to `0o555`/`0o444`.
Type bits come from the native mode, a genuine host-level read-only file
still fails its write at the native fs layer, and guest `chmod`/`chown`
continue to override through the overlay. POSIX hosts are unaffected: the
synthesis is gated on `process.platform === "win32"`.
Both HostFileSystem and NodePlatformIO funnel native stats through the
overlay, so the fix covers every host-backed stat/fstat/lstat path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t-perms # Conflicts: # host/src/platform/native-metadata.ts
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.
Why
On Windows there is no POSIX permission model. Node's
fs.statSyncreportsevery host filesystem entry as either
0o666(writable) or0o444(read-only): there is no owner/group/other split, no execute/"search" bit on
directories, and
chmodcannot express POSIX bits at all.That breaks host-backed mounts for any guest process that drops privileges —
for example a php-fpm worker running as a non-root user id — in two ways:
(search,
X_OK) bit on every path component. Because Windows neverreports a search bit, the privilege-dropped worker cannot traverse any
host-backed directory: the entire mounted tree is untraversable and every
request fails.
uploads, and cache under the mounted tree, so the worker must be able to
write there. On POSIX, hosts grant this by
chmod-ing those directoriesworld-writable. On Windows that
chmodis a no-op and never reaches thisoverlay, so the intent is invisible here.
This is a host-platform boundary, not a gap in the kernel's POSIX
enforcement: Windows ACLs don't map onto POSIX permission bits, so the kernel
cannot enforce them anyway. The fix belongs at the point where native Windows
metadata is translated into the POSIX model the guest sees.
What changed
When the native mode carries no meaningful permission bits (Windows only),
NativeMetadataOverlaynow synthesizes host-backed entries asworld-accessible —
0o777for directories,0o666for files — so aprivilege-dropped guest can both traverse and write the sandbox it was given.
The one attribute Windows does expose is still honored: read-only entries map
to
0o555/0o444.Guarantees preserved:
layer.
chmod/chowncontinue to override through the overlay.process.platform === "win32".Both
HostFileSystemandNodePlatformIOfunnel native stats through theoverlay, so the change covers every host-backed
stat/fstat/lstatpath.Validation
Adds
host/test/platform/native-metadata.test.tscovering the synthesizedbits, the read-only mapping, and the POSIX-host pass-through.
Split out from
fix/windows-host-dir-search-bits(one fix per PR). Thecompanion PR covers the unrelated spawn-pid allocator fix.
🤖 Generated with Claude Code