Add a per-rule flag — tentatively LANDLOCK_RULE_PATH — to landlock_add_rule so a path_beneath rule applies only when the access targets the exact inode the rule was created from, not when it targets a descendant.
Current behavior
Within a single ruleset layer, when the kernel evaluates an access on path F, it walks from F up the filesystem hierarchy and uses the first rule it encounters; that rule's allowed access bits determine whether the layer permits the access. In effect:
A layer grants access to F if any rule on F or any ancestor of F grants it.
This is what makes a directory rule recursive: granting RW on /a covers everything under /a.
Proposed behavior (opt-in, per rule)
A rule created with the new flag would not propagate down the hierarchy. The layer would grant access to F only if a rule exists on F itself with the matching bits. Existing rules without the flag keep today's recursive semantics.
A layer grants access to F if a non-inheriting rule on F grants it, or any inheriting rule on F or an ancestor of F grants it.
(Layer composition across stacked rulesets is unchanged — still intersection.)
Motivation / use case
Building user-facing sandboxes (interactive agents, file-scoped tools) that prompt the user to grant access incrementally. A common pattern is "grant this directory so the tool can work inside it" — but today that necessarily exposes every sensitive nested path (~/.ssh, ~/.aws, ~/.gnupg, browser profile dirs, ...). The sandbox author currently has no way to express "grant this directory, but require a separate explicit grant for each subdirectory the tool wants to descend into."
Concrete example: an agent is granted access to /home/user/projects/. With current semantics, that immediately covers /home/user/projects/secrets/, /home/user/projects/.envrc, etc. With a non-inheriting rule on /home/user/projects/, listing the directory and touching files directly in it would work, but descending into projects/secrets/ would trigger a separate denial → re-prompt → narrower grant.
Add a per-rule flag — tentatively
LANDLOCK_RULE_PATH— tolandlock_add_ruleso a path_beneath rule applies only when the access targets the exact inode the rule was created from, not when it targets a descendant.Current behavior
Within a single ruleset layer, when the kernel evaluates an access on path F, it walks from F up the filesystem hierarchy and uses the first rule it encounters; that rule's allowed access bits determine whether the layer permits the access. In effect:
A layer grants access to F if any rule on F or any ancestor of F grants it.
This is what makes a directory rule recursive: granting RW on /a covers everything under /a.
Proposed behavior (opt-in, per rule)
A rule created with the new flag would not propagate down the hierarchy. The layer would grant access to F only if a rule exists on F itself with the matching bits. Existing rules without the flag keep today's recursive semantics.
A layer grants access to F if a non-inheriting rule on F grants it, or any inheriting rule on F or an ancestor of F grants it.
(Layer composition across stacked rulesets is unchanged — still intersection.)
Motivation / use case
Building user-facing sandboxes (interactive agents, file-scoped tools) that prompt the user to grant access incrementally. A common pattern is "grant this directory so the tool can work inside it" — but today that necessarily exposes every sensitive nested path (~/.ssh, ~/.aws, ~/.gnupg, browser profile dirs, ...). The sandbox author currently has no way to express "grant this directory, but require a separate explicit grant for each subdirectory the tool wants to descend into."
Concrete example: an agent is granted access to /home/user/projects/. With current semantics, that immediately covers /home/user/projects/secrets/, /home/user/projects/.envrc, etc. With a non-inheriting rule on /home/user/projects/, listing the directory and touching files directly in it would work, but descending into projects/secrets/ would trigger a separate denial → re-prompt → narrower grant.