10.1 The Control Socket

peinit serves every runtime command on a Unix stream socket at /run/services/peinit/control.sock, created during Phase 1 infrastructure setup and existing for the lifetime of the system. Its wire protocol is specified in PSPU §4; this chapter is how peinit implements its side. A second socket beside it, the jobs socket, is the door for submitting jobs rather than administering services; it is §10.7.

10.1.1 Creation and protection #

The socket is created with SOCK_CLOEXEC | SOCK_NONBLOCK and a listen backlog of 32, and unlinked when peinit drops it. Accepted connections come from accept4 with both flags, so no connection descriptor is ever inherited by a service.

peinit sets no POSIX mode bits on the socket, on the notification socket, or on anything else it creates. Under KACS, mode bits are not what governs access — a Security Descriptor is — so setting them would be inert.

What governs access is the descriptor on the socket inode, which the kernel checks at connect() before any peer identity is established. peinit creates /run/services/peinit/ and stamps the control socket explicitly, after binding and before anything can connect :

O:SYG:SYD:(A;;GA;;;SY)(A;;GA;;;BA)(A;;FW;;;AU)

Every authenticated principal may connect. FW is the file-write generic right, which is what connect() on a pathname socket needs. Reaching the socket grants nothing on its own: every command is checked against the control descriptor or the target service's descriptor, with the token captured at accept (§10.2). Admitting only SYSTEM and Administrators would make that check moot for everyone else, since a descriptor that grants a principal something could never be reached by them.

The notification socket is stamped explicitly too, with a descriptor of its own that grants SYSTEM and the Service group rather than Administrators (§10.5). The jobs socket carries a broader descriptor again, because reaching it is a different permission (§10.7).

10.1.2 Connections #

peinit accepts a connection, obtains the peer's token, and only then admits it against the connection limits:

KeyDefaultMeaning
Machine\System\Init\MaxControlConnectionsPerUser16Concurrent connections one caller may hold, counted by the user SID of its token. SYSTEM is exempt.
Machine\System\Init\MaxControlConnections256Concurrent connections in all: a bound on peinit's descriptors, set well above what callers reach.
Machine\System\Init\MaxRequestSize65536Maximum request size, in bytes.
Machine\System\Init\ConnectionTimeout30Seconds before an idle connection is closed.

The per-user limit is what keeps one caller from taking the connections everyone shares: with every authenticated principal able to connect, a single overall limit would let anyone fill it and lock administrators out. SYSTEM is exempt, as it is from MaxJobsPerSubmitter, because what it does is the machine's.

A connection over either limit is closed at the socket level, before any request is read and without a response — there is no error code for it, because there is no protocol state in which to deliver one. A peer whose token cannot be obtained is closed the same way.

The jobs socket has its own three, under Machine\System\Init\: MaxJobsConnections (64), MaxJobMessageSize (32768) and JobsConnectionTimeout (30), plus a fourth bound that is the submitter's rather than the connection's, MaxJobsPerSubmitter (64). All four are read at boot and on reload-config, and are listed with the other operational keys in the registry key reference.

10.1.3 The peer token #

The token is read once, when the connection is accepted, through the kernel's peer-token socket option (getsockopt(SOL_KACS, KACS_SO_PEER_TOKEN); the Peios Kernel TRM §3.5). It is the identity the peer thread was acting under when it connected, so a peer that was impersonating is captured as the impersonated identity — which is what makes access decisions reflect the identity a client is actually operating under rather than its underlying service identity.

Because it is captured once, a peer that changes identity mid-connection is still evaluated against the identity it connected with.

10.1.4 Idle and waiting #

A connection is idle only when it has nothing in flight. One blocked on a wait=true operation, on a job-stop with wait, or with output still buffered, is never idle and is never closed by ConnectionTimeout — it stays open until the operation or job resolves, bounded by the operation's own timeout rather than the connection's. A job wait has no timeout of its own; it is bounded by the job.

A wait is answered when its operation reaches a terminal state, with the lifecycle acknowledgement carrying the service's state at that moment. Two cases are answered differently. An operation that failed because peinit could not execute it (§8.2) is answered with an INTERNAL_ERROR whose message carries the operation's result, not with an ok carrying an unchanged state. And an operation whose service has been discarded by the time it resolves — a stop that drained a definition-removed entry (§10.3) — is answered with the state the service last had, since there is no entry left to ask. Neither answer costs the connection or the listener.

peinit handles one frame per readiness turn, and processes no further frames from a connection while a wait is pending on it. Pipelined requests are therefore serialised behind a wait.

10.1.5 Timestamps #

Every timestamp peinit puts on the wire is derived by projecting a monotonic event stamp through the current offset between the realtime and monotonic clocks. Elapsed-time decisions stay monotonic; only the presentation is wall-clock.

Edit this page