On 5/28/26 19:32, aenri wrote:
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
correct there is an issue with dominance resolution, atm it only works for
exact match paths. One potential work around is to use priority rules
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.
So yes, this is finding the rule dominance. It is on the list of todo items.
The impact it would have would greatly depend on the number of states/rules
that needs to be resolved, but like you said if done right it shouldn't slow
things down too much, and that is better than not compiling.
This is indeed going to be much more of an issue in the future, so it is
something that needs to be done soon.
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?
this would replace exact/non-exact which was a hack to provide this behavior
for the exact match case, which is the most common
- When I have a patch, would you all prefer a GitLab PR or a patch sent to the
list?
either works, though gitlab is going to get replies sooner as it is more
active, and more of the developers are working there
- Is there any existing discussion or work on this that I've missed or should
be aware of before working on this patch?
there is some existing discussion around fixing dominance, there are even some
old patches that need to be completely reworked now, so they aren't really
useful
>
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!
The change would be a means to track the rule, in the accept node/state (a
set). Unioning the sets when creating the accept state/perms, and then a
conflict resolution routine if you hit a conflict.
Generally speaking this has been waiting on us to finish the front end
refactoring but this could be done just for x rules atm, using the pointers to
cod_entries in the set.
Thank you,
Aenri Lovehart