feat(services): PostgreSQL as a service MixEngine runs (T34, T34a) - #6
Merged
Conversation
…s on (T34a) CreateProcessAsUserW requires the token it is given to be able to open the window station and the desktop the child starts on. A station granted to BUILTIN\Administrators rather than to a logon SID is one a token holding that group deny-only cannot open, and the child dies at STATUS_DLL_INIT_FAILED before its first instruction. Measured rather than guessed: on the Windows runner the restricted child exited 0xC0000142 on WinSta0 while the same spawn from this process's own token ran and printed. restricted::admit adds an entry for the child's own user to both objects, once per process and only where this process holds an enabled Administrators, so an ordinary machine writes to nothing.
hyper's dispatcher lets exactly one request through before it has said it wants one, and every request after that only once the connection task has been polled since the last response. Sending straight away raced that task: the request was refused before it was written, with `canceled: connection was not ready`, which reads like a daemon that hung up. The CLI client meets this on every command, because the handshake spends the one free request. Reproduced on WSL at roughly one run in ten of the daemon's runtimes suite, and seen once on the Linux CI leg; fifteen runs after the fix are clean. Fixed in the client and in the three test suites that reuse a connection. The suites that open one per request are already covered by hyper's first-request allowance.
The window station was the wrong object. Granting the user WINSTA_ALL_ACCESS on WinSta0 and every right on its desktop changed nothing; that route is reverted here rather than left in, because it wrote to a shared machine object for no gain. Bisecting the restriction on an elevated machine found the real one: nothing disabled runs, Power Users disabled runs, Administrators disabled dies at STATUS_DLL_INIT_FAILED. An elevated administrator's token carries a default access control list naming SYSTEM and BUILTIN\Administrators and nothing else, because that group is the token's owner — so disabling it leaves a child with no access to the kernel objects it creates itself, including the ones the loader and CSRSS create while it is starting. keep_what_a_child_creates_reachable merges one allow entry for the token's own user into that list, unconditionally: it changes a token just made and no object anybody else can see. Verified in an elevated shell, which is the configuration the runner has and a developer's machine does not.
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.
PostgreSQL becomes a service MixEngine can run: a recipe that lays down the files, a first-run
initdbritual, apg_hba.confthat admits nothing but the local machine, and a superusercredential that is named rather than written down.
The suite that judges it starts a real server, queries it with the password MixEngine generated,
stops it, and asserts the ritual does not run twice. It runs on all three operating systems in CI,
against a real PostgreSQL fetched by the workflow.
T34a — a supervised child never inherits Administrators
Getting there needed the Windows spawn path rewritten. A daemon started elevated used to hand its
whole token to every child; now every supervised process and every one-shot is created from a
restricted copy with
BUILTIN\Administratorsand Power Users disabled. ADR 0010 records thedecision.
Two findings are written down where the next person will meet them:
at
0xC0000142before its first instruction. The cause is the token's default access controllist: an elevated administrator's names
SYSTEMandBUILTIN\Administratorsand nothing else, sodisabling that group leaves the child unable to open the objects it creates itself. The window
station was the plausible candidate and was measured innocent — that is recorded too, so the
afternoon is not spent twice.
one request before its connection task has signalled ready. The CLI's handshake spends it, so
every real
mixcommand was request number two and could fail withconnection was not ready.Reproduced on Linux 1 round in 10, then 15 clean rounds after
ready().await. This one was a livebug in
mix, not only in tests.Verification
CI run 32392948163 is green on all seven jobs —
lint,testandbenchon Windows, macOS andLinux — with the PostgreSQL suite passing against a real server on each.