Stained Glass OS

0012. Principals and elevation: who is an administrator, and how anything gets to root

Context

David's proposal (vision backlog item C1), in his words:

We'll have regular users, administrators that run as the system user, and potentially the kernel level would be the Linux root. Not sure if it's a good security model but potentially the system user has sudo access to get to root. Even if that literally means running a sudo su from an elevated shell.

He flagged his own doubt, and the stakes are the brief's: security equivalent to or better than Windows, on machines that remote-support tools and domain administrators will manage. Elevation ("Run as administrator", installers that demand it), Group Policy enforcement, the Control Panel and Edge's sandbox all build on whatever is decided here, so it has to be settled before them.

What the system does today

These are established by the code, not proposed:

So "administrators run as the system user" is already how the code decides administrative rights. What is open is how a human gets there, and whether that path continues to root.

The fact that decides the architecture

Wine is not a security boundary between processes of the same Unix user. Every Windows program a user runs is a Unix process with that user's uid. With kernel.yama.ptrace_scope at 0 (see Evidence for what the image does), any of them can attach to any other — read its memory, inject code into it — whatever tokens and integrity labels wineserver has assigned. At 1, ptrace is limited to descendants, but a same-uid program can still tamper with another's files, its environment and the programs it starts. Either way, same uid means no boundary the kernel will defend.

Windows' UAC keeps an unelevated program from driving an elevated one with integrity levels and UIPI, enforced by the Windows kernel. Wine's integrity labels are enforced only by wineserver, on wineserver objects; they do not stop ptrace. An "elevated" process under the user's own uid is not elevated in any sense that holds. Real elevation must run the elevated program as a different Unix account, started by something privileged after consent, so the kernel separates the two.

Options

A. Administrators' whole sessions run as the system user

An administrator logs in and their desktop runs as sgsystem.

Everyone's session — administrators included — runs as their own unprivileged Unix user. "Run as administrator" (and an installer's manifest demanding elevation) asks a small privileged elevation broker, which:

  1. shows a consent prompt on the secure surface the lock screen already uses (ADR 0009) — out of reach of the user session's programs;
  2. checks the requester is an administrator, and for consent requires their own password through PAM (Windows' "credential prompt" behaviour; a consent-only prompt can come later for fleets that want it);
  3. starts that one program as the administrative identity (sgsystem at first — see below), outside the user's uid;
  4. records who asked, for what, and the outcome in the journal.

This is UAC's shape. The kernel then separates the elevated program's process from the session's. Its display is a second channel, and is covered under Consequences: X11 lets any client inject input into, or read, any other window on the same display, so an elevated program shown on the session's own X server could still be driven by the programs it is meant to be protected from.

Which identity elevated programs run as. At first, sgsystem — it is the only administrative identity wine-sg recognises, and it is what installers need (HKLM, Program Files, services). Later, per-administrator elevated accounts (alice → alice-admin, with her SID plus Administrators) would make attribution exact and stop elevated programs sharing an account with services. That needs wine-sg to map an account to a user SID plus a group, which is the same work as domain group mapping (P2), so it waits for that.

C. The system user gets sudo to root

Separately from A or B: sgsystem may sudo to root.

Decision

B + D, decided by David on 2026-09-22.

Prompts, as on Windows (David, 2026-09-22):

Administrators are the members of a local group, sg-admins, which is also the group allowed to use sudo: one membership grants both. Domain groups map onto it later (P2).

Nothing here is safe to build until ADR 0013 is decided and implemented.

Evidence

Measured in the booted image (sg-image, 2026-09-22; kernel 6.12.107+deb13-amd64), over ssh:

Unix account Windows identity Administrator
sguser (uid 102) S-1-5-21-0-0-0-1102, name empty False
sgsystem (uid 101) NT AUTHORITY\SYSTEM, S-1-5-18 True

Also found: an ordinary user's identity has no account name (WindowsIdentity.Name is empty — the SID has no name mapping), so programs that show or log the signed-in user get nothing. Unrelated to elevation, but it is the same identity layer; tracked in the multi-user debt list.

Implementation (2026-09-23)

The security-blocker family (ADR 0013, debt D14/D16/D17/D18/D19) is fixed, so this is unblocked, and the core landed:

The consent prompt (landed 2026-09-24). The first plan was to reuse the lock surface as is. That did not work: while locked, sg-lockd puts a lock screen up, and a lock screen over a consent prompt is wrong. sg-compositor gained a SECURE mode instead. It isolates the session exactly as LOCK does, showing and sending input to privileged clients only, but it tells watchers secure rather than locked. RELEASE ends it and never undoes a real lock. A LOCK during a prompt promotes it to a lock, and no prompt may start over a locked machine. The broker finds the requester's own compositor (checked by SO_PEERCRED), engages SECURE and runs sg-consent.exe on a private X server on the privileged socket. Anything that goes wrong denies. Evidence: sg-compositor make test-secure covers the keylogger, focus-steal and lock-interplay cases, and fails against a SECURE that does not isolate. sg-session make test-consent runs the broker and prompt end to end with PAM under pam_wrapper. It fails against a broker that skips the administrator check, and against one that skips SECURE.

Elevated programs get a display of their own (built 2026-09-26, bug B56; shipped in sg-compositor 0.2.0+sg6, sg-session 0.1.0-40, wine-sg 10.0-79). Status (2026-09-26): shipped. The VM gate sg-image make elevated-test passes 13/13: the installer shows on its own display and gets the real keyboard, a session program cannot connect to that display, it installs to Program Files with a Start menu shortcut and an Apps & features entry, and Add someone else to this PC creates the account. Also fixed on the way: sg-brokerd's fixed PATH lacked /opt/wine-sg/bin (the elevated program exited 127).

The interim "share the session's display" never worked and was never shipped: as SYSTEM the elevated program could not even connect to the user's Xwayland ("Authorization required"), and had it, any program in the session could have typed into it or read it. So each elevated program now runs against its own X server, exactly as the Consequences below require:

Gates: sg-compositor make test-elevated (the real sg-elevated-run as sgsystem against the real compositor; a session adversary's XTEST, XSendEvent and XGetImage reach nothing of the elevated window; mutant-proven, including a build that puts the elevated program on the session display), sg-session make test-consent (the prompt's and lock screen's X servers now admit only their own account), and sg-image make elevated-test (a real NSIS installer through consent in the booted VM: window appears, real keyboard installs to Program Files with a Start menu shortcut for the user; "Add someone else to this PC").

Still open: per-administrator elevated accounts wait for SID/group mapping (P2).

Consequences

Amendment (2026-09-24): SYSTEM may ask for a fixed list of root operations

Decided by David: approved.

The Control Panel (sg-shell's sg-control) changes machine settings the way Windows' does: create and remove accounts, change an account's type or password, rename the computer, join a domain, set the time zone and time sync, check for updates. Those are root operations on Linux. They go through sg-admind (sg-shell admin/), a root service started by a systemd .path unit, which serves requests dropped in a spool only the SYSTEM account (sgsystem) can write.

This changes "SYSTEM is unprivileged on Unix": SYSTEM may now request, not perform, a fixed, validated list of root operations. That matches Windows, where LocalSystem outranks an administrator, and it keeps the principles of this ADR:

Gate: sg-shell test/admind-check.sh (every operation and every refusal; dropping the owner check or logging passwords turns it red).