Repository navigation
linux: a wrap that starts over reads the disk again - #644
Conversation
Since #638 a wrap that starts over kept the directories it had listed and each pattern's finished walk. A host that wrote a file and then installed a rule denying it, while a command was being wrapped, got a command that could read the file: the rule was walked over a listing made before the file was there. A wrap that starts over now keeps nothing, so what it hands out was read after its configuration was installed. It still ends: after two restarts it walks without giving the thread back. And an attempt is left as soon as its configuration is seen to be replaced, not walked to its end.
It undoes the join of #638: the kept walks, the anchor in their key and their charge to the budget go with the walks themselves. The budget and the listings are again made by each attempt. Of the three join cases one stays, under another name: a budget that arrives during the denyRead walk is the one the wrap ends by.
Comments only. The walk without a turn keeps timers and I/O callbacks out, not promise continuations, nor anything that runs while the network is still being initialized, so it is not a proof that the wrap ends. And a configuration installed after the last check is the next wrap's.
antdres
left a comment
There was a problem hiding this comment.
No blockers. This fixes the problem reported on #638.
Checked on Linux with real bubblewrap, head 26469d8, same steps as in the #638 review (a wrap is in flight on a 63,000-entry tree; the host writes proj/key.pem, then calls updateConfig() with a rule that denies proj/**/*.pem):
result of cat proj/key.pem |
|
|---|---|
| before #638 (60e5e9f) | Permission denied |
main (c7adb1e) |
prints the file's contents |
| this PR | Permission denied |
Same result on every run (3 of 3 each side).
With the same rules installed again in place of a new rule, at 4 ms steps across the wrap: the file is read in 22 of 23 timings on main and 3 of 24 here. Those 3 are replacements that land after the wrap's last configuration check, while the mandatory-deny search runs. The code before #638 lets them through as well (6 of 23), and so does v0.0.78, so that is not this PR's.
The new tests do their job: with main's source under them, five fail (the four new cases and the adapted one on the bound); with this PR's source all pass.
Generated by Claude Code
Fixes the blocker found in review after #638 was merged. It is on
mainand in no release.What was wrong
Since #638 a wrap that starts over kept the directories it had listed and each pattern's finished walk. So, while a command is being wrapped: the host writes
proj/key.pem, then callsupdateConfig()with a rule that deniesproj/**/*.pem. The wrap starts over, walks the new rule over a listing ofproj/made before the file was there, and hands out a command that reads the file. The same with the same rules installed again.#638 called that "as old as one long walk". That was wrong: the rule was installed after the file existed, and the wrap claims to apply it.
What changes
sandbox-utils.tsandread-deny-glob.tsare again what they were before linux: a wrap that starts over keeps what it has walked, and ends #638.Not kept for unchanged rules either: a rule dropped and installed again within one attempt looks unchanged from both ends.
Who sees a difference
A caller whose configuration is replaced twice during one wrap: the third attempt holds the thread for one whole walk, as every wrap did before #628. One replacement holds nothing.
Measured
The two cases above, real bubblewrap, 400,150 files, 3 runs each: denied before #638, read on
main, denied here.Six
**rules over the same tree, Node 22 / Bun 1.4.2, as multiples of an undisturbed wrap (about 1 s), on a busy machine:updateConfig()during the wrapmainTesting
Four new cases: each of the two above, with the replacement in the middle of the walk and in its last listing. #638's four cases on keeping are gone, and its case on the bound is adapted. Seven mutations, each failing a test; five cases fail on
main's source. Linux full suite: nothing that passes onmainfails here, those four aside.