1.1.10 — apply_devfs_ruleset verb (terminal isolation)#205
Merged
Conversation
lib/run.cpp:745-746 had paired `devfs -m P ruleset N` and `devfs -m P rule applyset` calls. Under 1.0.0+ rootless they EACCES'd silently, leaving the jail with the host's default devfs view — silent loss of a security control even when the spec set terminal.devfs_ruleset. New ApplyDevfsRuleset verb (full 7-file pattern) wraps the paired set+applyset shape atomically. validateAbsolutePath on mountPath, ruleset bounded 1..65535. Wire taxonomy grows 26 -> 27. lib/run.cpp's terminal-isolation block routes through verb when socket detected; legacy devfs(8) exec preserved. Tests: apply_devfs_ruleset_minimal covers boundaries + shell-meta + traversal rejection. Suite grows 1314 -> 1315. GPU unhide (lines 775-783) still bare — needs separate verb (AddDevfsUnhideRule), lands in 1.1.11.
User asked to combine 1.1.10 + 1.1.11 — both are devfs fixes in lib/run.cpp and the verb pattern is the same shape. Bundle GPU auto-unhide (lib/run.cpp:775-783) into this PR. New verb add_devfs_unhide_rule wraps `devfs rule add path X unhide` + applyset. Restricted to unhide action (devfs has hide/unhide/mode/group/user; only unhide has a sensible privops use case). Path-pattern validator allows alnum+.+_+-+/+*; rejects leading slash + shell metas. Wire taxonomy now 26 -> 28 (two verbs in this release instead of one). lib/run.cpp's GUI auto-unhide block goes from 3-call sequence (add + add + applyset) to 2 verb calls (each verb internally includes applyset). New tests add_devfs_unhide_rule_minimal + extended dispatch_covers_every_verb. Suite grows 1314 -> 1316.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes silent loss of terminal isolation under rootless.
lib/run.cpp:745-746's paireddevfs -m <jail/dev> ruleset <N>+devfs -m <jail/dev> rule applysetcalls EACCES'd for non-root operators, leaving the jail with the host's default devfs view (which exposes raw TTYs, /dev/mem, etc.) even when the spec explicitly setterminal.devfs_ruleset: 4.This is particularly bad because
devfs_rulesetis a security control. The operator configures it expecting hardening; the call fails silently; the jail runs with more device exposure than intended. Same shape as 1.1.5 (securelevel) and 1.1.6 (RCTL).New verb:
apply_devfs_rulesetWraps the paired set+applyset shape — both ops are meaningless without the other, so a single verb handles them atomically. Wire taxonomy grows from 26 to 27 verbs.
validateAbsolutePathon mountPath (rejects shell metas and traversals); ruleset bounded 1..65535 (devfs ruleset 0 is the implicit "no rules" default).Call-site change
lib/run.cpp's terminal-isolation block detects the privops socket and routes through the new verb; legacydevfs(8)exec preserved for the non-privops path.Coming next
lib/run.cpp:775-783still has three bare devfs calls for GPU auto-unhide (devfs rule add path 'dri' unhide+ siblings + applyset). Different argv shape — needs a separateAddDevfsUnhideRuleverb. That's 1.1.11.Audit chain status
/Tests
tests/unit/privops_pure_test.cppgainsapply_devfs_ruleset_minimalcovering: typical input, ruleset boundaries (1, 65535), ruleset=0 rejection, empty/relative/shell-meta path rejection.dispatch_covers_every_verbextended.Suite grows from 1314 to 1315.
Test plan
crate runwithterminal.devfs_ruleset: 4— verifydevfs -m <jail/dev> show(as root) lists ruleset 4 (was 0/default in 1.1.9)Generated by Claude Code