Open popov-nikita opened 4 years ago
On 2020-11-23 03:53, Nikita Popov wrote:
Hello, i've discovered particular issue where passing strings ending with '/' as directory name in mkdir syscall results in incorrect logging of directory name.
(snip reproducer)
type=PATH msg=audit(1606129593.392:85): item=0 name="/tmp/try.d" inode=16 dev=00:2f mode=040755 ouid=1000 ogid=1000 rdev=00:00 nametype=PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 type=PATH msg=audit(1606129593.392:85): item=1 name=(null) inode=16 dev=00:2f mode=040755 ouid=1000 ogid=1000 rdev=00:00 nametype=PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 type=PATH msg=audit(1606129593.392:85): item=2 name=(null) nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 type=PATH msg=audit(1606129593.392:85): item=3 name=(null) inode=16 dev=00:2f mode=040755 ouid=1000 ogid=1000 rdev=00:00 nametype=PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 type=PATH msg=audit(1606129593.392:85): item=4 name=(null) inode=17 dev=00:2f mode=040755 ouid=1000 ogid=1000 rdev=00:00 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
Ok, agreed. I can reproduce this on f32. Items 0 and 4 should be the only ones there.
In my opinion this is caused by the 'audit_compare_dname_path' function: https://github.com/linux-audit/audit-kernel/blob/ed1c04e9643cefd49de227830d0c63c68dcf2b75/kernel/auditfilter.c#L1301 Variable 'pathlen' is the length of 'path' which is original userland string (in our case - "poc/"). Variable 'dlen' is the length of directory name without any trailing '/'. In our case this is the length of "poc" string Variable 'parentlen' is computed by 'parent_len' function and should be 0. So given all that condition
if (pathlen - parentlen != dlen)
evaluates to true and strings don't match. This is what happens in __audit_inode_child function where we fail to find already existing parent.
Thanks for the very clear reproducer and the sleuthing. This will need a closer look. It may be as simple as checking for a trailing '/' and treat it similarly. As another quick data point, "mkdir -p /tmp/try.d/poc/./" denial works as expected.
Hello, i've discovered particular issue where passing strings ending with '/' as directory name in mkdir syscall results in incorrect logging of directory name. Steps to reproduce behavior:
1) Create proof-of-concept directory:
# mkdir /tmp/try.d
2) Add directory watch rule:# auditctl -S all -a always,exit -F dir=/tmp/try.d
3) Change cwd & create subdirectory as such:It's important to use '/' here at the end of mkdir's argument
After all these steps we will get the following logs:
Here the name of directory being created is completely missing and several empty PATH entries exist
In my opinion this is caused by the 'audit_compare_dname_path' function: https://github.com/linux-audit/audit-kernel/blob/ed1c04e9643cefd49de227830d0c63c68dcf2b75/kernel/auditfilter.c#L1301 Variable 'pathlen' is the length of 'path' which is original userland string (in our case - "poc/"). Variable 'dlen' is the length of directory name without any trailing '/'. In our case this is the length of "poc" string Variable 'parentlen' is computed by 'parent_len' function and should be 0. So given all that condition
if (pathlen - parentlen != dlen)
evaluates to true and strings don't match. This is what happens in __audit_inode_child function where we fail to find already existing parent.