Skip to content

tools9p integration: the sibling-prefix probes test pathwithin(), not grantcovers() - #1054

Merged
pdfinn merged 7 commits into
masterfrom
claude/vigilant-cerf-8jgrrv
Nov 3, 2026
Merged

pdfinn merged 7 commits into
masterfrom
claude/vigilant-cerf-8jgrrv

Conversation

@pdfinn

@pdfinn pdfinn commented Nov 3, 2026

Copy link
Copy Markdown
Member

Summary

provision_sibling_prefix looked like a hole: a /tmp/veltro:rw grant seemed to give child 16 /tmp/veltro/ok. In the full script the grant succeeded. Alone it was refused. Neither is a hole. The two runs were different commands.

  • The script's command. 18c45e6 changed the probe's grant to -p /tmp/veltro/ok:rw, and the merge of test(veltro): align campaign readiness checks #549 (7c03b05) kept that line. The line is tab-indented, unlike the rest, which makes the change easy to miss. The child asks for exactly its parent's grant, an ordinary directory, so the grant is correct.
  • The copy run alone. d534517's version of the probe, and the provision_sibling_mixed probe beside it, still read -p /tmp/veltro:rw. Under that grant /tmp/veltro/ok is a policy root's descendant, and grantcovers() correctly refuses it.

No earlier probe, lingering emu, $ROOT/tmp/veltro/cow state or timing is involved. The nsconstruct: /tmp/veltro/cow/0-408d82fa is from an earlier session line was missing only because overlays are keyed by the granted path:

  • 408d82fa is /tmp/veltro, and add94451 is /tmp/veltro/ok.
  • Only /tmp/veltro's overlay holds a staged scratch/0 from earlier probes, so only a probe granting /tmp/veltro has anything to set aside.

The probes had stopped testing anything

  • Sibling probe. /tmp/veltro/ok was never a string prefix of /tmp/veltroevil. /tmp/veltroevil also didn't exist, and grantcovers() refuses a path that doesn't exist before any component check.
  • Mixed probe (under /tmp/veltro). The policy-root rule refuses every path other than the grant itself, so the component check never decides anything. The "good" path, /tmp/veltro/ok, was also refused on its own, so the atomicity check could not fail.
  • Confirmed by mutation. With pathwithin() reduced to a plain string-prefix test, master's sibling probe still passes and still lists /tmp/veltro/ok rw.

Changes

tests/host/tools9p_integration_test.sh only. No tools9p or nsconstruct change was needed.

  • provision_sibling_prefix: grants /tmp/veltro/ok and asks for the sibling /tmp/veltro/okevil, then for /tmp/veltro/ok. The probe creates both directories itself, so only pathwithin()'s component check can refuse the sibling. It no longer depends on what earlier probes left behind.
  • provision_sibling_mixed: the same grant, asking for paths=/tmp/veltro/ok:rw,/tmp/veltro/okevil:rw. The grantable path comes first, so the probe fails if anything is provisioned before every path has been checked.
  • provision_policy_root_descendant (new): the exact command from the investigation, under -p /tmp/veltro:rw with the refused write before it. /tmp/veltro/ok exists and must be refused with denied path /tmp/veltro/ok (outside ...).
  • provision_covered_descendant is left alone; tools9p integration: the covered-descendant probe grants an ordinary directory #1053 fixes it.

Testing

Linux AMD64, headless build (./build-linux-amd64.sh headless, then mk install in appl, appl/mpeg, appl/veltro and tests).

  • The three probes alone on a clean tmp/: 3/3 pass.
  • The full script: 45 passed, 1 failed. The failure is provision_covered_descendant (tools9p integration: the covered-descendant probe grants an ordinary directory #1053). The three probes pass in it.
  • The three probes alone right after the full run: 3/3 pass. The result is the same alone, after a run and inside the script.
  • Mutation, with pathwithin() as a plain string-prefix test: both sibling probes fail. Master's sibling probe still passes under the same mutation.
  • Mutation, with grantcovers() lacking its policy-root check: provision_policy_root_descendant fails with "a policy-root grant minted a descendant".
  • Grant spellings checked: validatepath() refuses a trailing / and //, and policyroot() lowercases, so no other spelling of a policy root escapes the rule.
  • /tests/runner.dis -v not run. It is unaffected, since this changes one host-side shell test.

Linux AMD64 Host Tests (1) still fails until #1053 (covered descendant) and #1052 (devletters_test) land. This branch is based on master and doesn't touch #1053's probe, so the two don't conflict.

Checklist

  • Code follows the existing style of the file(s) modified
  • No .dis build artifacts committed from appl/ or tests/
  • Documentation updated (if applicable): n/a
  • No secrets, API keys, or credentials included

Generated by Claude Code

… grantcovers()

The sibling-prefix probe looked as if a policy-root grant minted a
descendant: the full script showed /tmp/veltro/ok granted to child 16,
the same command run alone refused it. They were not the same command.
18c45e6 changed the probe's grant to -p /tmp/veltro/ok:rw; the merge of
#549 kept that line, while d534517's copy of it (and the mixed probe
beside it) still read -p /tmp/veltro:rw. The script asks for exactly its
own grant, which is allowed; the copy asks under a policy root, which is
refused. No earlier probe, lingering emu, cow overlay or timing is
involved: each gives the same result alone, after a full run, and in the
script. The cow line was missing because the overlay key is the granted
path's (0-408d82fa is /tmp/veltro's), and only /tmp/veltro's overlay
holds a staged scratch from earlier probes to set aside.

Both probes had stopped testing anything. A grant of /tmp/veltro/ok was
never a string prefix of /tmp/veltroevil, which did not exist; under
/tmp/veltro every non-equal path is refused by the policy-root rule
before the component check matters, and the mixed request's "good" path
was refused on its own, so its atomicity check could not fail. With
pathwithin() reduced to a string-prefix test, master's probes still pass.

Now the grant is /tmp/veltro/ok and the sibling /tmp/veltro/okevil, both
made by the probe, so only the component check refuses it; the mixed
request names the grantable path first. A new probe pins the shape that
looked like a hole: under -p /tmp/veltro:rw, after a refused write,
/tmp/veltro/ok is refused. Checked by mutation: a string-prefix
pathwithin() fails the two sibling probes, grantcovers() without its
policy-root check fails the new one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195u6z6W3TbdAx7jg6RqhYy

pdfinn commented Nov 3, 2026 •

Copy link
Copy Markdown
Member Author

Update: all three fixes for the failures that weren't this PR's have merged: #1052 (devletters_test, wmsize_test), #1053 (provision_covered_descendant) and #1055 (the sed_test ShortScripts race). Master, now including #1051 too, is merged into this branch (78e76c8). On that tree, run locally, the whole tools9p integration script gives 46 passed, 0 failed, and sed_test passes.

iOS Build & Simulator Test failed again on 78e76c8. It isn't this PR's either: it fails on and off on master as well (86de120, 62ce2a6), in 5 of the last 30 CI runs.

  • The failure: in every failing run, simctl launch --console-pty writes nothing for the whole 60 s cap and never starts the app, so no test output appears.
  • A passing run: the app's first line appears at once and PASS within 5–9 s.

#1057 handles it: a launch that has written nothing in 20 s is stopped and made again (up to 3 tries), and a failure prints the simulator's state.


Generated by Claude Code

#1053's comment above provision_covered_descendant and this branch's
new provision_policy_root_descendant block both land just before that
probe; both are kept. The whole tools9p integration script passes
locally: 46 passed, 0 failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195u6z6W3TbdAx7jg6RqhYy
claude and others added 2 commits November 3, 2026 07:13
Brings in #1055, the fix for the sed_test race that was this PR's one
red job (Linux AMD64 Build & Test, ShortScripts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195u6z6W3TbdAx7jg6RqhYy
claude and others added 2 commits November 3, 2026 09:32
Brings in #1057: the iOS verify step relaunches a simulator launch that started nothing, the one failure left on this branch (iOS Build & Simulator Test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195u6z6W3TbdAx7jg6RqhYy
@pdfinn
pdfinn merged commit 91d58f8 into master Nov 3, 2026
42 of 43 checks passed
@pdfinn
pdfinn deleted the claude/vigilant-cerf-8jgrrv branch November 3, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants