8000 test(minimald): prove on a real kernel that a blocked cohort refuses pre-flip UDP 443 (T87) by minimal-foundry[bot] · Pull Request #2648 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

test(minimald): prove on a real kernel that a blocked cohort refuses pre-flip UDP 443 (T87) - #2648

Merged
norrietaylor merged 4 commits into
mainfrom
agent/2606-prove-on-a-real-kernel-that-a-blocked-cohort-rej
Oct 27, 2026
Merged

norrietaylor merged 4 commits into
mainfrom
agent/2606-prove-on-a-real-kernel-that-a-blocked-cohort-rej

Conversation

@minimal-foundry
@minimal-foundry minimal-foundry Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor

T87 — Prove on a real kernel that a blocked cohort rejects a pre-flip UDP 443 socket

slice: S12
kind: task
covers: BEP-018
size: M
est: 40 code, 160 tests
executor: agent
difficulty: unknown ground
model: strongest
diagnostics: the leg records NOT RUN with its gate where the host has no root netns or no nft
observability: one line per step of the leg
layers:
- kernel:
- crates/minimald/tests/netns_root_integration.rs: a leg that opens a UDP 443 socket in a host_ip member's leaf before the cohort flips to blocked, expects ECONNREFUSED on the next datagram after the flip, and a send again after the block lifts, against the loaded classifier table (#2606)
test: cargo nextest run -p minimald --run-ignored only a_blocked_cohort_rejects_a_pre_flip_udp_443_socket
produces: none
consumes: none
proof: On a real kernel, a host_ip member's UDP 443 socket opened before the cohort turns blocked is rejected after the flip and sends again after the block lifts.
depends on:
- blocked by #2558

Proof

The native lane's minimald-root-integration job now has a leg, a_blocked_cohort_rejects_a_pre_flip_udp_443_socket. It loads the installer's real classifier table on a real kernel and opens a UDP socket to 127.0.0.1:443 in a host_ip member's own allow leaf. It flips the cohort to blocked: the process moves into boxes/quic443-blocked and the installed helper adds the own leaf to quic443_blocked_leaves. The pre-flip socket then gets ECONNREFUSED, and the listener gets nothing. After the helper removes the leaf, the same socket sends again and the listener receives the datagram. The leg was NOT observed passing on a real kernel in this session, because this box has no sudo and no nft.

Notes from the agent: The real-kernel leg did not run here. This box has no sudo, no nft and no root reach, so only the gate path ran: the skip, and NOT RUN for the missing nft. The CI lane holds the first real evidence. Read its run before you trust the proof.

Design choices that the lane run must confirm:
(1) Port 443 is privileged, so the leg runs a UDP listener as sudo -n python3. A listener is necessary because without one, the kernel itself answers port unreachable before the flip. python3 is a declared system dependency in AGENTS.md. If the runner has no python3, the leg fails loudly.
(2) I expect the first datagram after the flip to return EPERM, because NF_DROP in the output hook gives EPERM. I expect the next datagram to report ECONNREFUSED from the reject's ICMP. The leg accepts EPERM, success or ECONNREFUSED on the first datagram, and it requires ECONNREFUSED by the next one at the latest.
(3) The install puts the helper and its sudoers rule in a root-owned mktemp -d /run/minimald-quic443-proof.XXXXXX, through the MINIMAL_OVERRIDE_QUIC443_HELPER and MINIMAL_OVERRIDE_QUIC443_SUDOERS knobs. Nothing goes to /usr/local/lib or /etc/sudoers.d on the host. Cleanup runs the installer's own --uninstall with the same knobs, then removes the directory.
(4) The leg takes …[truncated]

Real-kernel run (arch C1): the minimald-root-integration job on fca73a8e (https://github.com/gominimal/minimal/actions/runs/40429271408/job/121942764926) passed the leg in 6.5 s. Its log shows step 1 through step 9, ending with step 8: the pre-flip socket sends again after the block lifts and step 9: the table, the helper and the scratch tree are removed. No line in the log contains NOT RUN.

Layer exception

The epic owner accepted this file outside T87's layers on 2026-10-27, for arch condition C1 (round 1):

  • .config/nextest.toml: a [[profile.ci.overrides]] entry with success-output = "immediate" for a_blocked_cohort_rejects_a_pre_flip_udp_443_socket, so the CI log shows the leg's steps.

Tests

line exit tail
cargo nextest run -p minimald --run-ignored only a_blocked_cohort_rejects_a_pre_flip_udp_443_socket 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-8926... Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc

Verify

min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

re/compose.rs:402:8
    |
402 | pub fn deferring_env() -> StoredEnv {
    |        ^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors

Base

The base branch moved while the coder worked; it was merged in before the tests ran.

Closes #2606


Generated by Claude Code

The leg loads the installer's classifier table over a scratch cgroup2
tree. It opens a UDP socket to 127.0.0.1:443 in a host_ip member's own
allow leaf. Then it flips the cohort the way the daemon does: the
process moves into boxes/quic443-blocked, and the helper adds the own
leaf to quic443_blocked_leaves. The pre-flip socket then reports
ECONNREFUSED. After the helper removes the leaf, the same socket sends
again. A root-bound listener on port 443 confirms each delivery.

The leg prints NOT RUN with its gate where the host has no nft or the
process is outside the root network namespace. (BEP-018, #2606)
@coderabbitai
coderabbitai Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c0184a12-7dd2-4910-ae90-56da0e996782

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@minimal-foundry
minimal-foundry Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor Author

Approved: every review thread resolved at fca73a8efa58.

@norrietaylor resolved the last thread, which releases the approval this review had withheld.

Nothing to do.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approved

Verdict APPROVE — No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-foundry minimal-foundry Bot added the review:approved minimal-review approved the current head label Oct 26, 2026
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The leg proves BEP-018 against the installer's real reject rule. It goes through the quic443_blocked_leaves set, the only rule that covers a socket made before the flip. It needs ECONNREFUSED, so a silent drop fails it. This matches §5.3 line 150: "an active reject, never a silent drop". The PR says nobody saw the leg run on a real kernel, and the leg exits green on NOT RUN. C1: read the minimald-root-integration job on this head and confirm step 8 printed, with no NOT RUN line, before merge.

Ruled at 9322713 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Copy link
Copy Markdown
Member

/revise

Round 1 of #2648, on arch condition C1 at 93227137 (#2648 (comment)). No round is in flight. The epic owner's policy is to fix a small arch condition in its PR. The owner accepts the one file outside T87's layers that this needs, as a layer exception. Add a "Layer exception" section to the PR body that names it.

Why. C1 asks the minimald-root-integration log to show step 8: the pre-flip socket sends again after the block lifts and no NOT RUN a_blocked_cohort_rejects_a_pre_flip_udp_443_socket line. On 93227137, the test PASSed in 6.4 s, but nextest captures a passing test's output. The log therefore holds neither line, and the condition cannot be checked.

  1. In .config/nextest.toml, add a [[profile.ci.overrides]] entry with filter = 'test(=a_blocked_cohort_rejects_a_pre_flip_udp_443_socket)' and success-output = "immediate". Add a one-line comment that says the arch review reads this leg's steps from the CI log (BEP-018). Do not change .github/workflows/.
  2. Change nothing else. Run cargo nextest run -p minimald --profile ci --run-ignored all -E 'test(=a_blocked_cohort_rejects_a_pre_flip_udp_443_socket)', and check that the output prints the leg's steps, or its NOT RUN line on a host without root or nft.

Generated by Claude Code

The arch review reads this leg's steps from the CI log (BEP-018), and
nextest captures a passing test's output by default.
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The leg proves the design's active reject on a pre-flip host_ip socket, against the real installed table. The test file is the same as on the earlier head, and the new nextest override only prints the leg's steps in the ci profile. The leg is still not observed on a real kernel. Section 5.3 line 150 requires an active reject, and a NOT RUN leg does not prove it. Link the lane run on this head as C1 says.

Ruled at fca73a8 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread .config/nextest.toml Resolved
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 2 unresolved threads — minimal-arch[bot] crates/minimald/tests/netns_root_integration.rs:2487, minimal-arch[bot] .config/nextest.toml:31. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-foundry minimal-foundry Bot removed the review:approved minimal-review approved the current head label Oct 27, 2026
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a /revise note, pushed as fca73a8efa58.

line exit tail
cargo nextest run -p minimald --run-ignored only a_blocked_cohort_rejects_a_pre_flip_udp_443_socket 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-9546... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc

Verify min task run agent-verify passed.

Outside the task's layers::

  • .config/nextest.toml

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

  • 👍 valid — crates/minimald/tests/netns_root_integration.rs:2487: Added a ci-profile override in .config/nextest.toml with success-output = "immediate" for this test, so the CI log now shows the leg's steps or its NOT RUN line on a pass. Installing nft in the job needs .github/workflows/, which is frozen, so this round makes the outcome readable and does not chang

On a real kernel, a host_ip member's UDP 443 socket opened before the cohort turns blocked is rejected after the flip and sends again after the block lifts. With this round, the minimald-root-integration CI log prints the leg's steps, step 8 included, or its NOT RUN line, so a reviewer can read which one happened.

Notes from the agent: Layer exception: .config/nextest.toml is outside T87's layers. The epic owner accepted it for arch condition C1, and the PR body needs a 'Layer exception' section that names it. This box has no root and no MINIMALD_NETNS_TEST, so the leg did not run its steps here. The output check proved only that the ci profile now shows a passing test's output. The C1 condition (step 8 present, no NOT RUN line) can be checked only on the CI log of the next head. The local branch also carried a merge of origin/main (7c353cf) from before this round, and I did not change it.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft October 27, 2026 01:04
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approved

Verdict APPROVE — every review thread is resolved; @norrietaylor closed the last one. The review of fca73a8efa58 withheld this approval on the threads open then. Posted as a comment: the App cannot approve its own pull request; the check and the label carry it.

@minimal-foundry minimal-foundry Bot added the review:approv 8BD0 ed minimal-review approved the current head label Oct 27, 2026
@norrietaylor
norrietaylor marked this pull request as ready for review October 27, 2026 02:03
@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Own review at fca73a8. The new root-integration leg opens a UDP 443 socket in a host_ip member's own leaf, blocks the cohort, sees ECONNREFUSED, and sends again after the block lifts, on the runner's real kernel. The ci profile override prints its steps. The linked run shows step 1 through step 9 and no NOT RUN line.


Generated by Claude Code

@norrietaylor norrietaylor changed the title T87 — Prove on a real kernel that a blocked cohort rejects a pre-flip UDP 443 socket test(minimald): prove on a real kernel that a blocked cohort rejects a pre-flip UDP 443 socket (T87) Oct 27, 2026
@norrietaylor norrietaylor changed the title test(minimald): prove on a real kernel that a blocked cohort rejects a pre-flip UDP 443 socket (T87) test(minimald): prove on a real kernel that a blocked cohort refuses pre-flip UDP 443 (T87) Oct 27, 2026
@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Babysitter approval at fca73a8: every merge gate passes at this head (arch PASS at fca73a8, zero open threads, every lane aggregator green). Squash title test(minimald): prove on a real kernel that a blocked cohort refuses pre-flip UDP 443 (T87) and the squashed message pass commitlint. Queued for squash merge.


Generated by Claude Code

@norrietaylor
norrietaylor added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit a558eb1 Oct 27, 2026
37 checks passed
@norrietaylor
norrietaylor deleted the agent/2606-prove-on-a-real-kernel-that-a-blocked-cohort-rej branch October 27, 2026 04:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review:approved minimal-review approved the current head

Projects

None yet

Development

Successfully merging this pull request may close these issues.

T87 — Prove on a real kernel that a blocked cohort rejects a pre-flip UDP 443 socket

1 participant

0