[apparmor] Some apparmor profile statements are not honored for an application
John Ernberg
john.ernberg at actia.se
Wed Sep 2 09:30:13 UTC 2020
Hi John.
(I am leaving most of my original reply in here in case others run into
the same problem, I was missing the --features-file because I missed
this part of the docs)
On 9/2/20 9:47 AM, John Johansen wrote:
> On 8/31/20 7:54 AM, John Ernberg wrote:
>> Hi,
>>
>> I seem to have a bit of an odd problem in that some of the profile
>> statements do not appear honored and the library loads they statements
>> allow are thus denied. There is the only program in the system so far
>> that is running confined. The program in question only handles files and
>> library loads.
>>
>> I double checked the syntax of the failing rules, they are aligned with
>> functional rules. I re-did them by copy-pasting the file name in the
>> audit message and then copy-pasted the flags from a functional rule,
>> just to be sure. No change.
>>
> example rules and profiles would help. If you don't want them on the
> public list you can send them to me directly
>
>> I have checked the statemachine produced with apparmor_parse -D
>> dfa-states and it looks correct, however, when I dump the statemachine
>> transitions in the kernel they are a little off compared to the
>> statemachine generated by apparmor_parse -D dfa-states command when
>> logging in aa_dfa_match on the kernel side, it really looks like the
>> machine makes incorrect lookups.
>>
> this is weird. What are you using to dump the kernel state machine?
(email client mangling risk)
@@ -464,8 +466,10 @@ unsigned int aa_dfa_match(struct aa_dfa *dfa,
unsigned int start,
equiv[(u8) *str++]);
} else {
/* default is direct to next state */
- while (*str)
+ while (*str) {
+ pr_err("apparmor: dfa: [%u] testing perm for
%s\n", state, str);
match_char(state, def, base, next, check, (u8)
*str++);
+ }
}
return state;
Then I match the [xxx] number with the statemachine from dfa-states
output. A bit into the string the transitions stop matching, and after
another bit into the string segments might get skipped or read past end
of string.
>
> you can compare the binary in userspace and the equivalent kernel
> blobs to make sure they are the same.
>
> Eg. for the ping profile on my system
>
> $ cat /sys/kernel/security/apparmor/policy/profiles/ping.3/raw_sha1
> 704b8eafff4dc11ede6b1843384fb7379f13028b
> $ sudo sha1sum /etc/apparmor.d/cache/bin.ping
> 704b8eafff4dc11ede6b1843384fb7379f13028b /etc/apparmor.d/cache/bin.ping
>
> and diff of binaries
>
> $ sudo diff -q /sys/kernel/security/apparmor/policy/profiles/ping.3/raw_data /etc/apparmor.d/cache/bin.ping
> $
>
> You need to be aware that the sha1 and raw_sha1 are different, you want
> the raw_sha1 and raw_data when comparing to the userspace file.
>
> Those two will correspond to the compiled blob in the file that is loaded
> into the kernel. If that blob contains multiple profiles each profile
> in the blob will point to the same raw_data, raw_sha1, but their
> individual sha1 file will differ (its taken from a subsection).
>
> The raw_data and raw_sha1 files reported by the profiles are the same
> that can be found in /sys/kernel/security/apparmor/policy/raw_data
> going through the profile just makes it easier to correlate with the
> policy on disk.
>
> Doing this check does not guarantee that what the kernel is using is
> the same as what you see in userspace, but it does show what the
> kernel should be using. This check will help us determine where we
> should be focusing the search
>
> The kernel unpacks the loaded blob into a native format so there
> is some data shuffling of what is actually used by the kernel. So what
> the kernel is using could be off for 3 reasons
> - the unpack is broken
> - there is kernel memory corrupts
> - there was a previous version of the profile loaded into the kernel
> and it is in use. Profile replacement is not atomic, when a mediation
> hook is entered the current policy what ever it may be at that
> point will be used, even if profile replacement happens while the
> hook is running. The new profile should be used in the next call to
> a mediation hook but there have in the past been bugs, causing the
> old profile to be used long past when it should.
>
>
>> I have noticed transitions to IDs other than those expected when
>> comparing to the dfa-states, and it seems to start skipping characters
>> in the paths or going beyond the end of the path string for some paths.
>> These paths are the paths for which statements are not honored.
>>
> how are you checking this? This should not be possible as it is the path
> that drives the state machine. That is the path is walked linearly one
> character at a time and we step to the next state in the state machine.
See diff chunk earlier in the mail.
>
> The only time we walk a path more than once per character is when doing
> profile matching, and the overlapping express match allows for a limited
> nfa stack of N states for backing up. iirc in 5.4 it is limited to 8
> states worth of backup.
>
>> Trying to add debug to the match_char macro on the kernel side seems to
>> break the statemachine completely, so I wasn't able to debug this route
>> further.
>>
> you can add stuff to the macro but you do need to be careful it is
> easy to break it
@@ -376,6 +376,7 @@ struct aa_dfa *aa_dfa_unpack(void *blob, size_t
size, int flags)
do { \
u32 b = (base)[(state)]; \
unsigned int pos = base_idx(b) + (C); \
+ pr_err("apparmor: dfa: current char %c\n", (C));\
if ((check)[pos] != (state)) { \
(state) = (def)[(state)]; \
if (b & MATCH_FLAG_DIFF_ENCODE) \
That chunk is all that I added, after that no statement in the profile
applies and (C) is mostly > 127
>
>> I'm running version 2.13.3 of the userspace tools, and kernel 5.4.24
>> (vendor kernel, can't upgrade, can't try mainline due to missing support
>> for the SoC I'm using), with the latest 5.4 stable patches for apparmor
>> applied on top.
>>
> can you run a debug kernel with custom patches if needed?
Slightly limited with my debug options due to working from home with
limited equipment, but I can definitely try patches as needed.
>
>> The rules is compiled on my machine (x86_64) and embedded in my target
>> (aarch64) readonly rootfs. Target has a readonly filesystem.
>>
> this should be fine the compiled policy tries to arch independent but it
> is always possible we have an bug in the native mappings. It is something
> to keep in mind, while trying to figure out what is going on
>
>> The rule is loaded on target with the following command:
>> /sbin/apparmor_parser -K -B /etc/apparmor.d/myprogram
>> Where myprogram is the profile for my program
>>
> what audit message/messages are logged when you do this
[ 4.478643] audit: type=1400 audit(1603443648.037:3):
apparmor="STATUS" operation="profile_load" profile="unconfined
" name="/usr/bin/myprogram" pid=533 comm="apparmor_parser"
The program is started later
>
>> So far I have not been able to create a shareable reproducer which,
>> unfortunately, makes this all the more harder.
>>
>> I would appreciate any suggestions in how to proceed or what kind of
>> info I should be looking at in order to find out what is going wrong.
>>
> First verify that the user space binary file and what the kernel expects
> are the same.
(from target)
# sha1sum /etc/apparmor.d/usr.bin.myprogram
90ca35aa2f57b3ab562c14a6927cef11fbc24d0c /etc/apparmor.d/usr.bin.myprogram
# cat
/sys/kernel/security/apparmor/policy/profiles/usr.bin.myprogram.1/raw_sha1
90ca35aa2f57b3ab562c14a6927cef11fbc24d0c
>
> Second, are you pinning the policy feature abi or using the kernel feature
> abi, and if you are using the kernel feature abi, what is the feature
> abi of the machine you are compiling on vs. the kernel you are loading
> policy on.
I wasn't, I had completely missed this feature. I extracted the
.features file from target kernel and provided that to the compiler with
--features-file
Everything now looks like I expect it to look. Thank you very much for
this hint.
Very curious results when this is skipped!
>
> Extracting the feature abi in apparmor 2.13 is a bit of a pita. For the
> machine you are compiling on look for the .features file in the cache
> directory. If you are not writing the cache, make a temporary cache
> in tmp
> mkdir /tmp/cache
>
> and add
>
> --cache-loc=/tmp/cache --write-cache
>
> to your compile.
My local machine doesn't have apparmor enabled, but compiled in.
>
> On the machine you are loading the policy on do the same thing. Make
> a temporary cache and compile a simple profile
>
> profile test { }
>
> will do.
>
> Compare the two feature abi files. >
> Also can you be more specific about the rules that are having problems?
> File rules, signal, and even which components. The more detail the
> better, feel free to substitue example values instead of real ones if
> you need to.
Only file rules are used at this time.
>
>
>> Thank you in advance.
>>
>> Best regards // John Ernberg
>>
>> (not subscribed to the mailing list)
>>
> thats fine just expect some moderation delay
>
Best regards // John Ernberg
More information about the AppArmor
mailing list