learn: decide the write tier by the granted path - #231
Merged
Merged
Conversation
collapse_write_paths had two branches: an existing path was recorded with a NOTE whatever its tier, while a missing path was walked up to its nearest existing ancestor and only there checked against the tiers. A Landlock grant on a directory is recursive either way, so mkdir in a protected directory got the grant that creating a file under the same directory was refused. Resolve the granted path first and apply the tier check once, so both routes skip Protected and warn with a diff on Guarded. Also move /root from Protected to Guarded. As a non-root caller /root is not writable anyway, and as root it is simply $HOME, where dotfile writes are as legitimate as in any other home directory. The old special case made learned profiles silently incomplete for root workloads and left the HOME != "/root" check unreachable. Fixes #217 Signed-off-by: Cong Wang <cwang@multikernel.io>
Contributor
Author
|
@ghazariann Please take a look. Thanks! |
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.
Fixes #217.
Problem
collapse_write_pathshad two branches that disagreed about tiers:NOTE, whatever its tier. Syscalls such asmkdirat,unlinkat,renameat2,symlinkatandlinkatrecord the parent directory, somkdir /root/foolanded here and got a recursive write grant on/root.open("/root/foo/bar", O_CREAT)reached/rootand was skipped with an error.A Landlock grant on a directory is recursive either way, so the same effective grant had two outcomes. The credential suffixes (
.ssh,.aws,.kube,.gnupg) had the same split, and Guarded paths had a milder one (NOTEon one route, warning plus sibling diff on the other).Fix
Resolve the granted path first (the path itself, or its nearest existing ancestor), then apply the tier check once. Both routes now skip Protected and emit the warning plus the unobserved-siblings diff on Guarded.
/root moves from Protected to Guarded
Looking at why
/rootwas Protected at all, the special case does not hold up:/rootis 0700 and not writable, so the rule protects nothing./rootis simply$HOME, where dotfile writes are as legitimate as in/home/user, which is already Guarded for that reason. The rule only bit in that case, leaving learned profiles silently incomplete.home != "/root"check inclassify_pathwas unreachable, because the Protected match returned first./rootis listed inGUARDED_PATHSunconditionally rather than relying on the$HOMEmatch. Learn records an open before the kernel denies it, so a non-root workload that pokes at/rootwould otherwise get a Normal grant with no warning.Protected is now
/plus the credential suffixes.Behavior changes
mkdir,unlink,rename,symlinkorlinkdirectly inside a Protected directory is now skipped with a warning instead of granted with aNOTE.NOTE.NOTE: observed a direct writemessage is gone. Warning wording is unified across both routes.Tests
test_write_grant_skips_protectedreplaces the/rootbased test: it uses a temporary.sshdirectory and covers both creating a file under it andmkdirinside it.test_write_grant_warns_guarded_homeruns the same two routes against a temporary$HOMEand expects the grant, the guarded warning and the diff each time.test_direct_write_root_skippedupdated for the unified "filesystem root" wording.learn_testpasses (41),sandlock-cliunit tests pass (6). The rest of the workspace suites were not run locally.docs/learn.mdtier table updated to match.🤖 Generated with Claude Code