init: a protocol you were not granted does not exist

The registry consults the open rows it has been parsing since P2, so
reaching a contract now takes a grant as well as a binding. A caller
without one is answered exactly as it would be for a name nobody ever
bound: same status, same empty reply, same absent capability, byte for
byte, and no log line on either path — klog_read is ungated, so a line on
one and not the other would be the oracle the design set out to remove.
Refusal and absence being one answer is what lets a supervisor later
narrow, fake or park a child's namespace without the child learning what
it was denied.

The manifest gains a third permission for a shape the plan did not
foresee: attestation is one hop, but the driver tree is three deep — the
PS/2 keyboard and mouse are spawned by ps2-bus, which the device manager
spawned — so no row could name them and PS/2 input would simply stop.
 lets a delegate vouch for what its children *reach*, never for
what they claim; the bind path is untouched, and the laundering deputy is
still refused.

The review found the receive side of a rule this track had already
written down. Every process holds a sendable handle to the registrar —
resolve installs one for anyone who asks — and ipc_reply_wait never asked
who owned the endpoint, so a stranger could dequeue there: take the
provider endpoints riding bind requests, and answer other clients' opens
in the registrar's name. Receiving is the owner's privilege, like binding
a signal or a timer; sending remains anyone's.

Suite 109/109.
This commit is contained in:
Daniel Samson
2026-08-01 04:44:15 +01:00
parent 1379b699f3
commit 7f3eb848f0
13 changed files with 670 additions and 24 deletions
@@ -0,0 +1,19 @@
.{
.name = .protocol_denied_test,
.version = "0.0.0",
.fingerprint = 0xab37a6fa7116698f, // Changing this has security and trust implications.
.minimum_zig_version = "0.16.0",
.dependencies = .{
// build-support supplies the shared recipe; kernel is implicit in
// every binary (the root shim + link script live there). The rest
// are exactly the homes of this binary's declared imports.
.@"build-support" = .{ .path = "../../../../build-support" },
.kernel = .{ .path = "../../../../library/kernel" },
// envelope: the errno the registrar answers a refused open with;
// vfs-protocol: the request and reply this fixture compares byte for
// byte, which is why it speaks the wire itself instead of using the
// Channel client.
.protocol = .{ .path = "../../../../library/protocol" },
},
.paths = .{""},
}