test: block-range — the discrimination fixture for range confinement (V2a)

A process acquires a block channel the way a filesystem does (consumer-hello
the device manager), confines ITSELF to blocks [1,3), then proves the clamp
and the gate: volume-relative LBA 0 maps inside the range and reads; a read
reaching past the range is refused; geometry reports the confined size; and
a confined caller can no longer call define_range (no widening, no escape).
It gates on argv so the ramdisk sweep leaves it silent in other boots, and
coexists with fat (ranges are per-badge).

Discrimination (verified by reverting usb-storage to pre-clamp f1bdce2~1):
the unconfined read still succeeds but define_range returns ENOSYS, so the
fixture cannot arm confinement and the case fails — exactly the property
the clamp adds. With the clamp: block-range 1/1.
This commit is contained in:
Daniel Samson
2026-08-09 17:25:43 +01:00
parent f1bdce25e0
commit c37402891a
7 changed files with 228 additions and 0 deletions
+16
View File
@@ -1234,6 +1234,22 @@ CASES = [
{"name": "device-authority",
"expect": r"DANOS-TEST-RESULT: PASS",
"fail": r"DANOS-TEST-RESULT: FAIL"},
# Per-sender range confinement (V2a, docs/volume-manager-plan.md): a process
# confines ITSELF to a block sub-range (as the volume manager confines a
# filesystem), then proves it cannot read past the range nor widen it. The
# security assertions are named explicitly so the case cannot pass without
# them; a confined read crossing the range must be REFUSED and a confined
# define_range must be REFUSED. Against pre-clamp usb-storage the define_range
# verb does not exist, so the fixture fails to arm confinement at all.
{"name": "block-range",
"smp": 4,
"timeout": 150,
"expect": r"(?s)(?=.*block-range: ok in-range-read)"
r"(?=.*block-range: ok out-of-range-refused)"
r"(?=.*block-range: ok geometry-is-confined)"
r"(?=.*block-range: ok confined-cannot-redefine)"
r"(?=.*block-range: VERDICT done)",
"fail": r"block-range: FAILED|DANOS-TEST-RESULT: FAIL"},
# IRQ teardown: an exiting driver's line is masked and its slot cleared (so no
# ISR notifies a freed endpoint), and a sibling owner sharing that endpoint
# keeps its own binding. A long-running driver never reaches this teardown path.