The spike (#6, PR #113) settled the
shape and answered the security questions. None of it is in src/. This issue is
the real thing: compact --elevate, the attached-read-only "full" mode that D10
left as an opt-in, and whatever later needs an elevated token.
What the spike already decided
Do not re-litigate these; they are measured in
docs/RESEARCH.md.
- One-way pipe (
PIPE_ACCESS_INBOUND, worker → parent) for progress, plus a
separate manual-reset event for cancellation. A duplex pipe deadlocks: I/O on a
synchronous file object is serialized, so a pending ReadFile blocks the
concurrent WriteFile.
- DACL
D:P(A;;GA;;;<user sid>) -- the launching user and nobody else, not
even SYSTEM. The elevated child is the same user one integrity level up, so it
opens without weakening anything.
- 128-bit random pipe name created with
FILE_FLAG_FIRST_PIPE_INSTANCE; abort
if the name is taken.
- The worker verifies its server (pid, image path, token SID) before it
streams anything.
- Declining is
ERROR_CANCELLED → ErrorCode::NeedsElevation → exit 4.
- Ctrl+C does not reach the elevated child. Cancellation is explicit, via the
event, and the worker must unwind rather than die.
- D11: the elevated half is one verb, re-validates its path against the
caller's own Lxss hive, and reads nothing from the pipe.
Work
Over-the-shoulder elevation
The one thing the spike could not measure. The user-only DACL works because a
split-token administrator's filtered and elevated tokens share a user SID. A
standard user who elevates by entering another account's credentials gets a
worker with a different SID, which that DACL denies.
Decide and implement one of:
- Detect it (compare the client SID after
ImpersonateNamedPipeClient) and fail
with a message that says what happened, or
- Grant the elevated identity explicitly in the DACL -- which means knowing it
before the pipe is created, and is not obviously possible.
Needs a second account on a test machine to verify either way.
Done when
compact <distro> --elevate runs the attached-read-only path end to end on a
machine where the unattached path leaves space behind, streams one progress bar,
propagates one exit code, detaches the disk even when interrupted, and declining
the prompt costs the user nothing but exit 4. Unit tests cover every failure
branch with injected errors; the integration test is gated like the rest.
The spike (#6, PR #113) settled the
shape and answered the security questions. None of it is in
src/. This issue isthe real thing:
compact --elevate, the attached-read-only "full" mode that D10left as an opt-in, and whatever later needs an elevated token.
What the spike already decided
Do not re-litigate these; they are measured in
docs/RESEARCH.md.
PIPE_ACCESS_INBOUND, worker → parent) for progress, plus aseparate manual-reset event for cancellation. A duplex pipe deadlocks: I/O on a
synchronous file object is serialized, so a pending
ReadFileblocks theconcurrent
WriteFile.D:P(A;;GA;;;<user sid>)-- the launching user and nobody else, noteven SYSTEM. The elevated child is the same user one integrity level up, so it
opens without weakening anything.
FILE_FLAG_FIRST_PIPE_INSTANCE; abortif the name is taken.
streams anything.
ERROR_CANCELLED→ErrorCode::NeedsElevation→ exit 4.event, and the worker must unwind rather than die.
caller's own
Lxsshive, and reads nothing from the pipe.Work
IElevationinterface +Win32Elevationbehind it, with a fake, so theoperation logic stays unit-testable (
CheckTokenMembership,ShellExecuteEx, pipe, event -- all through theWin32Apitable so theerror branches are injectable).
ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | NO_DRIVE_LETTER | NO_LOCAL_HOST), compact, detach. Path re-validatedagainst the registry before anything is opened.
ProgressSinkso an elevated run rendersidentically to an unelevated one.
--elevateoncompact, and the interactive prompt when full mode is whatthe user needs. Never implied by a bare
compact.worker is cancelled mid-operation.
worker's failures carry a remedy like every other error.
Over-the-shoulder elevation
The one thing the spike could not measure. The user-only DACL works because a
split-token administrator's filtered and elevated tokens share a user SID. A
standard user who elevates by entering another account's credentials gets a
worker with a different SID, which that DACL denies.
Decide and implement one of:
ImpersonateNamedPipeClient) and failwith a message that says what happened, or
before the pipe is created, and is not obviously possible.
Needs a second account on a test machine to verify either way.
Done when
compact <distro> --elevateruns the attached-read-only path end to end on amachine where the unattached path leaves space behind, streams one progress bar,
propagates one exit code, detaches the disk even when interrupted, and declining
the prompt costs the user nothing but exit 4. Unit tests cover every failure
branch with injected errors; the integration test is gated like the rest.