A privilege-separated display manager.
The graphical login for a Linux system, split across a root daemon and an unprivileged interface that talk over a documented protocol. Written in Rust, for a runit and elogind system, as the login layer of the operating system work.
The program that holds root and owns the screen.
A display manager sits at an unusual intersection. It authenticates, so it handles credentials. It starts sessions, so it holds root. It draws an interface, so it parses input from whoever is at the keyboard, including whoever should not be. Most designs in this category put all three in one process, which means an interface bug and a root compromise are the same event.
It is also the layer with nothing beneath it to blame. When a display manager fails it usually fails holding the display, so the diagnostic surface a normal program would rely on is the thing that just broke. A user is left at a black screen on their only computer, with no visible way back.
That inverts the usual priorities. The privilege boundary and the recovery path are not hardening to add once it works; they are the design, and everything else is arranged around them.
The requirements that came out of that.
Every one is about limiting what a failure can reach, because at this layer a failure reaches the whole machine.
- A privilege boundary that a session bug cannot reach back through
- Credentials that do not outlive the moment they are used
- No path where a compromised interface can start a session
- Recovery from a crash that does not depend on the screen still working
How the authority was split.
Four calls that define the security model. Each has a simpler opposite, and the simpler opposite is what most of the category does.
Stated as decisions rather than features, because each cost something real. What follows is which way this one went and what it bought.
Three processes, not one
A root daemon starts a per-login worker that owns the whole authentication lifecycle, and that worker forks the session child which irreversibly drops privilege before running anything of the user's. The process holding the authentication handle never becomes the user, and the process that becomes the user never holds it. A single-process design is far simpler and makes any bug in it a root bug.
The interface is unprivileged and replaceable
The greeter runs as its own unprivileged account and speaks to the daemon over a versioned unix-socket protocol with a length-prefixed frame, a size cap and a version handshake. It cannot start an unauthenticated session and cannot pass a free-form command across the boundary: it may only name a session the system itself discovered. Publishing that protocol under a permissive licence is what lets somebody write a different interface without inheriting the daemon's licence.
Single-threaded and blocking, deliberately
No async runtime, no thread pool. A process that forks must not have other threads alive when it does, and the entire model depends on forking correctly at the exact moment privilege changes. Giving up concurrency here buys the one guarantee the security model cannot do without.
A black screen is treated as a defect, not an accident
Terminal state is restored from signal handlers using only calls that are safe to make from one, rather than from ordinary cleanup code that a hard crash never reaches, with a service hook and a check on the next boot behind it. Text consoles stay available as a way back in. It is the recovery path for the case where the thing that failed is the thing you would have used to diagnose it.
The decision that mattered.
One call per build, taken with a real alternative on the table. The alternative is named here, and so is what choosing against it cost.
Three processes where one would have worked.
Authentication, privilege and the interface are split across separate processes that talk over a defined protocol, rather than living together in one program the way most of this category does.
It is the decision everything else on the page follows from. Once the interface cannot reach the authority, the remaining questions are about how the pieces talk, which is engineering. Left in one process, no amount of care in the rest recovers the property.
- The alternative
- One process, running as root, doing all three. It is the shape of the tool this one is replacing and it is genuinely simpler: no protocol to define, no version handshake, no serialisation, no partial failure between components, and a session lifecycle you can read top to bottom in one file.
- What it cost
- A large amount of complexity, permanently, for a program whose whole job is to show a password box. A wire format with a version negotiation, a socket whose peer has to be verified, forking at exactly the right moments, and a set of failure modes that only exist because the pieces are separate. All of it is code that can be wrong, in a program where being wrong is expensive.
- Why the trade holds
- In a single process, a bug in the part that parses keyboard input is a bug in the part that holds root, because they are the same address space. That is not a hypothetical risk profile, it is an identity. The split converts the worst case from full machine compromise into a crashed interface that could not have started a session anyway. Complexity is a price that can be paid once and reviewed; the single-process design charges its price only once, and never refunds it.
No boot figure, no memory figure, no audit result. The security argument above is structural, about what a failure can reach, and nothing here has been independently reviewed or formally verified. That absence is stated rather than papered over: this is pre-v1 software making a design argument, not a program with a security record.
The reasoning, published.
This page describes a problem class rather than a client engagement. These are the pieces where the same reasoning is worked through in full.
- ArticleChoosing an init system, and why 0dyssey runs runitThe system this one is built for: what starts a machine, how you judge one init against another, and why the service that supervises a login is the shape it is.
- ArticlePackage models, and the debt you defer by freezingHow software arrives on a machine and moves between known states, which is what a display manager has to be installed and upgraded through without stranding anyone at a black screen.
- Product0dyssey, the operating systemThe operating system this is the login layer of: the named composition, the decisions taken, and what does not exist yet.
Ask about any of these.
The specifics are not on this page. Ask for them directly, or send the problem you actually need solved.