Repository navigation
windows: let the sandbox user stat the folders above a granted path - #661
Open
karljamoralin wants to merge 1 commit into
Open
karljamoralin wants to merge 1 commit into
karljamoralin wants to merge 1 commit into
Conversation
This branch has not been deployed
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.
Fixes part 1 of #657.
Cause
acl grantputs the sandbox user's ACE on each granted path and nothing on the folders above it, so the sandbox user can't stat them. Anything that stats each path component fails: git's repository discovery (fatal: failed to stat 'C:\Users\me\code': Permission denied) and Node's JSfs.realpathSync(EPERM ... lstat).Listing a folder's parent lets an account read the folder's attributes by path (
GetFileAttributesExW, which git uses), but not open a handle to it.CreateFileWalways addsSYNCHRONIZE | FILE_READ_ATTRIBUTESto the requested access, so a handle-based stat (libuv whereGetFileInformationByNameis missing) fails even on the profile root.Change
New ACE kind
read_attrs:(A;;FILE_READ_ATTRIBUTES|SYNCHRONIZE;;;<sb>), with no inheritance flags. It's refcounted inworking_aceslike the other kinds, and is part ofKIND_GRANT, soacl revokeand crash recovery remove it. It grants no listing, contents, write or DACL rights.Which ancestors: after a successful grant batch,
grant_ancestor_attrswalks each target's ancestors up to, but not including, the volume root. It skips ancestors that are themselves grant targets. A newStatProbechecks whether the sandbox user already holds both bits on each ancestor. The probe runsAuthzAccessCheckwith a client context built from the sandbox SID (no logon), on a copy of the DACL that leaves out:Administratorsallow ACEs, which the child token holds deny-only.A failure on one ancestor logs a warning and releases the hold if this call added it.
No subtree walk: a converge triggered by a
read_attrshold (take, release, crash recovery) goes through the newapply_read_attrs. When the sandbox ACEs on disk differ from the wanted ones by at most this ACE, it writes the one object withSetKernelObjectSecurity, or nothing if the folder already matches.SetNamedSecurityInfoWre-propagates a folder's inheritable ACEs to every descendant even when only an object-only ACE changes, which took 75 s on a profile root here (srt-win acl stamp is deterministically ~30s/path when the parent directory is a Windows system-managed directory (user profile root, %TEMP%) — breaks Windows sandbox initialize() #457).SetSecurityInfopropagates too unless the handle was openedMAXIMUM_ALLOWED, and that open fails with a sharing violation on a profile root.Smoke test: new
smoke-aces.ps1row A32 grants a folder under%LOCALAPPDATA%\Tempand checks three things:[IO.Directory]::Exists) and through a handle (CreateFileW);ReadAttributes, Synchronizeallow;acl revokeleaves none behind.Overlap: #523 adds a non-propagating writer for object-only ACEs, and #579 changes deny handling in the same functions. This PR doesn't change how grants and denies are written.
Testing
On Windows 11 x64 (26200), with
srt-win.execross-built forx86_64-pc-windows-gnuat the pinned 1.98.1 (CI builds MSVC), grantingC:\Users\<me>\srt657\repo:git rev-parsein a non-repo allowed folder, viasrt-win execfatal: failed to stat '...\srt657': Permission deniednot a git repositorynode -e "fs.realpathSync(...)"EPERM ... lstat '...\srt657'fs.readdirSync('..')from the allowed folderEPERMEPERM(no listing granted)CreateFileW(FILE_READ_ATTRIBUTES)on...\srt657and on the profile rooticaclson...\srt657and the profile root after grantsrt-sandbox:(S,RA)without(OI)(CI)icaclsafteracl revokeD:P)acl grant/acl revoketimesrt-win execSTAT_FAILonTemp,Local,AppDataand a handle failure on the profile rootNew unit tests:
read_attrs_is_object_only_and_does_not_propagatecovers:read_attrshold next to that grant;stat_probe_ignores_sandbox_aceschecks that the probe ignores its own ACE, needs both bits, and doesn't count listing the parent.cargo clippy --all-targets -D warningsandcargo fmt --checkare clean, and all 55 lib tests pass on the box. I have not runsmoke-aces.ps1locally, because it reinstalls with the test sublayer; A32 runs in CI.Known limits:
read_attrsrows fails to parse them, so downgrading mid-session is not supported.