Repository navigation
T154 — A VM host's own-address box reaches a host exposure through the guest relay - #3002
Conversation
An own-address box that names host.min.internal, or whose allow_subnets covers the alias, now has its TCP and UDP frames to the host alias passed on by the guest relay. The VM host daemon's gate decides them against the current [host-exposures] table. A box that does not name the host stays refused, and the relay names that refusal by the host-alias rule. A native relay keeps the alias refused.
…s-own-address-box-reaches-a-host-expos
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
|
Approved: no findings at Nothing to do. Verdict APPROVE, posted as a comment: the App cannot review its own pull request; the check and the label carry it. Clobber: none seen. |
There was a problem hiding this comment.
arch-review: PASS · the full ruling
The change conforms to §7.1. The guest relay cannot read the [host-exposures] table, so it passes a naming box's TCP and UDP frames at the alias on to the VM host daemon's gate. That gate reads the current table for each flow, applies the same naming predicate, and refuses Minimal's own listeners first (§7.1 lines 250 to 252). The pass-on is off by default and is set only on the vsock attach, so a native relay keeps the alias at its exposure ports. No conditions.
Ruled at 7eedd68 against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.
|
Round 1 of 10 on the runtime's review findings: the coder changed nothing. Revise round 1. One thread, judged invalid. No code change this round, so no commit. An undeclared allow_subnets is allow-all in this codebase (03-spec R2.1, the egress module header). NET-160 refuses only when the box neither names host.min.internal nor has an allow_subnets that covers the alias. An allow-all dimension covers the alias. The VM host daemon's gate on main (crates/minvmd/src/net/egress_gate.rs, AliasOpenings::for_box) uses the same rule with is_none_or. If the guest used a different rule, the two sides would disagree on one declaration. If a box with only allow_dns_hosts must not reach host exposures, that is a spec change to NET-160 and a change to egress_gate.rs, which is outside this task's layers. Review threads the coder judged:
|
The guest relay now passes host-alias flows on to the VM host gate for a box whose allow_subnets covers the alias (NET-160). The NET-004 arm still asserted the old silent drop. It now asserts that the own-address box fetches the marker at the exposed port and is refused at a port outside the [host-exposures] table.
There was a problem hiding this comment.
arch-review: PASS · the full ruling
The compare changes only the own-address leg in scripts/session-e2e.sh. The old leg asserted a drop at the host alias for a box that covers the alias. Section 7.1 line 251 says that box reaches the exposure, so the old leg was wrong. The new leg asserts reach at the exposed port and refusal at port 18089, and each failure is hard. The comment at lines 22477-22486 still says the reach is refused. Update it in a later change.
Ruled at e5e414f against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.
|
Round 2 of 10 on a failed check suite, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review. On a VM host, an own-address box whose egress covers or names host.min.internal reaches the port that the user's [host-exposures] table opens, and the VM host gate still refuses it at a port outside the table. A box that does not name the host stays refused by its own relay under the host-alias rule. Notes from the agent: Revise round 2. The e2e failure was the NET-004 arm in scripts/session-e2e.sh. It asserted that an own-address box with --allow-subnets 0.0.0.0/0 must never reach the host alias at the exposed port. Under NET-160 that subnet covers the alias, so this task makes the reach correct, and the arm asserted superseded behaviour. I touched scripts/session-e2e.sh outside the layers for this reason. The arm now fetches the marker from the alias at the exposed port and expects a refusal (curl exit 7 or 28) at the unexposed port, from the same box. I could not run the e2e on this box, because it needs a VM lane. The ci-macos-success excerpt showed no error beyond its exit code. I assume that it is the aggregator of the failed e2e job on the macOS runner. The refusal half for a box that does not name the host stays pinned by the switch.rs unit test, not by the e2e. |
…s-own-address-box-reaches-a-host-expos
The NET-160 round dropped the e2e refusal arm. A second own-address box whose rules do not cover the alias now asserts the silent drop again.
|
Round 3 of 10 on a failed check suite, pushed as
Verify On a VM host, an own-address box whose egress covers host.min.internal fetches the marker from the port the [host-exposures] table opens, and stays refused at a port outside it. A second own-address box that does not name the host stays refused at the exposed port: its relay drops the connect silently. The e2e asserts both boxes, and the unit test pins the guest relay's behaviour and its host-alias refusal line. Notes from the agent: Revise round 3. The directive gives only the failed test-kvm and ci-linux-kvm-success checks. Its log excerpt shows the workflow's own script source (the ::error:: echo lines) and no failure output, so I was not able to find th 8000 e cause of the failure. I did not run the KVM e2e on this box. This round restores the NET-004 refusal arm in scripts/session-e2e.sh on a second own-address box (--allow-subnets 192.0.2.0/24, no host.min.internal). The task layer asks for that arm, and the previous round removed it instead of moving it. If test-kvm fails again, read the full job log for the first NET-160 or NET-004 ::error:: line that the run printed. No out-of-scope files were touched. |
There was a problem hiding this comment.
arch-review: PASS · the full ruling
The compare adds one e2e arm and a clean merge of main. The production files do not change, so the PASS on e5e414fc stands. The new arm uses an own-address box that does not name the host. It asserts the silent drop that §7.1 line 248 requires, so the NET-004 leg is hard again. No conditions.
Ruled at b5e098b against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.
There was a problem hiding this comment.
Read at b5e098b. The disputed thread does not hold: NET-160 refuses only when the box neither names host.min.internal nor covers the alias, and an undeclar
8BD0
ed allow_subnets covers it. Arch passes.
|
/review |
T154 — A VM host's own-address box reaches a host exposure through the guest relay
slice: S21
kind: task
covers: NET-160
size: M
est: 90 code, 120 tests
executor: agent
difficulty: needs care
model: standard
diagnostics:
min bugbundles carry the guest daemon log and the VM host daemon log, so a refused flow shows which side refused itobservability: the guest relay's refusal line names the rule
host-alias; the VM host daemon's gate logs the box and the port it decidedlayers:
- relay:
- crates/minimald/src/net/switch.rs:
compiled_egressno longer refuses the host alias in the guest for an own-address box that nameshost.min.internal, so the VM host daemon's gate decides the flow against the current table- crates/boxes/src/core/egress.rs:
SwitchOwnAddressescarries what the guest relay needs to pass that flow ontest: cargo nextest run -p minimald own_ip_box_exposure_passes_the_guest_relay
produces: none
consumes: none
proof: On a VM host, an own-address box that names
host.min.internalreaches a port the user's[host-exposures]table opens, and a box that does not name the host stays refused.depends on:
- blocked by #2689
- blocked by #2936
Proof
On a VM host, the guest relay passes TCP and UDP frames to host.min.internal on to the VM host daemon's gate when an own-address box names host.min.internal (or its allow_subnets covers the alias). That gate already decides the flow against the current [host-exposures] table. A box that does not name the host stays refused at the guest relay, and the refusal line says rule_matched="host-alias". A native relay keeps the alias refused. The test own_ip_box_exposure_passes_the_guest_relay checks all three cases.
Notes from the agent: The guest relay knows that it is on a VM host only when it attaches over the vsock shuttle. attach_to_switch_vsock now calls BoxGate::mark_host_gated, and the relay then decides by a second compilation that passes the host alias on (SwitchOwnAddresses::with_host_alias_passed_on). With this approach the production caller in gvproxy_network.rs and the compiled_egress callers in dns.rs need no change. The predicate that 'names the host' copies the one in the minvmd gate (AliasOpenings::for_box): host.min.internal in allow_dns_hosts, or an allow_subnets that covers the alias, or no egress declaration. NET-160 names both halves, so I included the allow_subnets half. The task note names only allow_dns_hosts. The guest relay now names its own drop at the host alias by the rule 'host-alias' in place of 'egress-infrastructure-destination', to satisfy the observability line. The hostname proxy's caller check and the sibling lookups still use the native compilation, so they do not pass the alias on. This is intentional. I also ran cargo clippy -p minimald -p boxes --all-targets (clean), cargo nextest run -p minimald net:: (426 passed) and cargo nextest run -p boxes core:: (362 passed). An end-to-end check on a real VM host is not possible on this box.
Tests
cargo nextest run -p minimald own_ip_box_exposure_passes_the_guest_relayVerify
min task run agent-verifypassed ([tasks.verify]).Base
The base branch moved while the coder worked; it was merged in before the tests ran.
Closes #2990