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. A supervise grant 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:
+17
-1
@@ -869,10 +869,26 @@ CASES = [
|
||||
r"(?=.*protocol-registry: restarted provider reached)"
|
||||
r"(?=.*protocol-registry: laundering deputy refused)"
|
||||
r"(?=.*protocol-registry: foreign signal binding refused)"
|
||||
r"(?=.*protocol-registry: foreign timer and exit binding refused)"
|
||||
r"(?=.*protocol-registry: foreign timer and exit binding refused)(?=.*protocol-registry: foreign receive refused)"
|
||||
r"(?=.*protocol-registry: capability-carrying pings did not exhaust the harness)"
|
||||
r"(?=.*DANOS-TEST-RESULT: PASS)",
|
||||
"fail": r"DANOS-TEST-RESULT: FAIL|protocol-registry: FAIL"},
|
||||
# Restriction stage one (docs/os-development/protocol-namespace.md): the
|
||||
# registrar checks `open` against /system/configuration/protocol.csv, and a
|
||||
# caller with no grant gets the same answer as a caller naming a contract
|
||||
# nobody bound. The scenario boots /protocol plus the input service, so the
|
||||
# forbidden name is genuinely BOUND — the fixture reads the namespace listing
|
||||
# to prove it — and then compares the refusal with an unbound name field by
|
||||
# field: status, node, payload length, the whole reply packet, and the
|
||||
# presence of a capability. All three failure shapes (refused-and-bound,
|
||||
# granted-and-unbound, neither) must collapse into one answer.
|
||||
{"name": "protocol-denied",
|
||||
"expect": r"(?s)(?=.*protocol-denied: granted open succeeded)"
|
||||
r"(?=.*protocol-denied: ungranted open refused as absent)"
|
||||
r"(?=.*protocol-denied: refusal is indistinguishable from absence)"
|
||||
r"(?=.*protocol-denied: ok)"
|
||||
r"(?=.*DANOS-TEST-RESULT: PASS)",
|
||||
"fail": r"DANOS-TEST-RESULT: FAIL|protocol-denied: FAIL"},
|
||||
# Device manager: a ring-3 service enumerates /system/devices, matches the PCI host
|
||||
# bridge to pci-bus, and spawns it — end-to-end proof of discover -> match -> spawn
|
||||
# -> driver-up (the spawned pci-bus logs "<N> functions found").
|
||||
|
||||
Reference in New Issue
Block a user