Hi all, 



I've recently run into a limitation while trying to configure AppArmor for use 
with non-FHS filesystem layouts, such as (and particularly for my use-case) 
Nix, where binaries live under /nix/store/<hash>/bin instead of the typical 
/usr/bin. I believe I've traced it to a minor shortfall in executable flag 
conflict resolution; the mechanism itself is an otherwise effective and 
reasonable solution, however all paths with wildcards anywhere within the path 
are treated the exact same within hfa.cc / pri_update_perm. This leads to 
system-breaking conflicts and unnecessary failures to 
compile DFA profiles despite one path being deterministically and 
provably more specific. Under FHS layouts, this would only rarely, if ever, be 
an issue, however with Nix's non-FHS layout it's most effective to use a 
wildcard to include all /nix/store/<hash>/bin folders as @{bin} entries, as 
opposed to generating an ever-changing gigantic file including every Nix store 
folder as an @{bin} entry. For example, /nix/store/*/bin/foo and 
/nix/store/*/bin/* are both evaluated through aare_rules.h+c into MatchFlags, 
and thus both have the same low priority when attempting to merge executable 
flags, despite /nix/store/*/bin/foo being a deterministically more specific 
path which shows intent to modify the permissions for the specific 
Nix-distributed binary. I've investigated a possible solution that leaves 
runtime enforcement and all conflict-free paths unaffected while compiling DFA 
profiles, but I thought it would be best to see if there are any 
positive/negative opinions from the maintainers on this idea before pushing too 
far on code or submitting some random PR.




My idea is to add on to the behavior of perms_t and pri_update_perm in order to 
resolve conflicts between two different MatchFlags by traversing the regex AST 
of both matching items and determining subset relationships between them only 
at compile time on a conflict. This subset relationship (e.g. 
/nix/store/*/bin/foo is a subset of /nix/store/*/bin/*, and thus more specific) 
is then used to prioritize the more specific MatchFlag. In a case where no 
subset relationship can be determined (e.g. patterns that overlap but where 
neither entirely contains the other), we would fall back to the existing 
conflict/error behavior. Considering the infrequency with which conflicts 
occur, even under Nix, I would expect this to have negligible if any noticeable 
performance effects at DFA compile time, and no performance effects during 
runtime enforcement. That said, when they do occur they're often severe; in my 
case, enough profiles failed to compile to leave my system completely unusable 
without disabling AppArmor.




Some questions about this process:


- Does this approach seem sound? Is there some context I'm missing about why 
executable flag priority is simply exact vs non-exact versus an approach 
similar to this?
- When I have a patch, would you all prefer a GitLab PR or a patch sent to the 
list?
- Is there any existing discussion or work on this that I've missed or should 
be aware of before working on this patch?




I'm open to any comments, questions, or concerns about this, I'd prefer to 
align on direction than to come in with a blind PR that no one wants or needs. 
I'd be happy to write up further about the changes I'd be making to achieve 
this as well!





Thank you,

Aenri Lovehart

Reply via email to