feat: authenticate Windows command launcher and signal helper

This commit is contained in:
2026-09-06 14:38:16 +00:00
parent 158fd8f3aa
commit 0383155b86
13 changed files with 1270 additions and 189 deletions
+29 -6
View File
@@ -1937,12 +1937,14 @@ import Windows APIs. Keep launch phases identical across platforms:
The first native adapter is now required to expose this contract through
`internal/client/supervisor.Supervisor`: the non-Windows adapter is test-only,
while the Windows implementation must perform token selection and Job setup
inside the same `Start` call. It may return only after the child has been
assigned to its kill-on-close Job and released; all token/session attempts must
be represented in the returned immutable identity. A failed start clears the
pre-launch barrier and produces one rejected lifecycle event; an uncertain
authorized row is never retried as a fresh process.
while the Windows implementation must perform token selection, launcher
authentication, and Job setup inside the same `Start` call. It may return only
after the launcher and shell are prepared, suspended, and assigned to the
kill-on-close Job; `Process.Release` crosses the later durable authorization
barrier. All token/session attempts must be represented in the returned
immutable identity. A failed start clears the pre-launch barrier and produces
one rejected lifecycle event; an uncertain authorized row is never retried as a
fresh process.
Implement one exhaustive token selector; do not scatter token fallback across
launch code:
@@ -2045,6 +2047,27 @@ effective token SID the required access.
Service exit therefore kills launcher, shell, and descendants in every crash
window. Recovery never signals or kills by PID alone.
The Windows implementation uses the same signed `rvbox.exe` for the private
`--launcher` and `--signal-helper` modes. The service creates one random
per-command generation and four byte-mode named pipes (`control`, `stdin`,
`stdout`, `stderr`) with a protected DACL containing only SYSTEM and the
effective token SID plus `PIPE_REJECT_REMOTE_CLIENTS`. The launcher receives
only the opaque channel name on its command line. Every control frame has a
fixed magic/version/type/generation/length/checksum header and a bounded JSON
payload; the service rejects a peer before reading launch material unless the
pipe client PID, process-creation `FILETIME`, token SID, session ID, and frame
generation all match the suspended process it created. The shell inherits only
the three explicitly listed stdio pipe handles. `Process.Release` writes the
authorized frame and waits for the launcher's release acknowledgement.
TERM starts a separate helper with a fresh one-pipe generation under the same
verified effective token/session. The helper authenticates identically, then
receives the target PID and creation time over the pipe, reopens the target,
checks creation time/SID/session, attaches to its private console, and emits a
bounded result. It receives no Job or stdio handle. A helper creation or attach
failure is recorded and may use the verified direct attach fallback before the
configured grace-period Job escalation.
Do not combine `CREATE_NEW_PROCESS_GROUP` with `CREATE_NEW_CONSOLE`: Windows
ignores the former, and it is unnecessary because every command owns a distinct
hidden console. For TERM, start a short-lived private signal-helper mode of the
+10 -3
View File
@@ -61,9 +61,16 @@ that command text is accepted once, output is journaled, lifecycle/terminal
events are durable, and a script cannot launch before its contiguous upload is
committed. The Windows build uses the same executor contract with the
platform-native adapter: a verified token is selected, the child is created
suspended, assigned to a kill-on-close Job, and only then released. The
durable `launch_phase` barrier is recovered as `interrupted` after a daemon
restart, so an uncertain release is never redispatched.
suspended, assigned to a kill-on-close Job, and held behind an authenticated
per-command launcher pipe. The daemon records `launch_prepared`, then the
durable `launch_authorized` transition sends the launcher's release frame; the
launcher resumes the shell only after that acknowledgement. The durable
`launch_phase` barrier is recovered as `interrupted` after a daemon restart, so
an uncertain release is never redispatched.
The Windows artifact is linked with the GUI subsystem (`-H=windowsgui`) so
service, launcher, and tray startup do not flash a console. Human-facing modes
still attach to a parent console explicitly when one exists.
Suite output is capped at 1 MiB and stored as `artifacts/suite.log`. A failed
run remains inspectable and can be moved back to `ready` with `recover`, then