On 2/11/20 5:58 AM, Paul Moore wrote:
On Mon, Feb 10, 2020 at 6:05 PM Orion Poplawski
<orion(a)nwra.com> wrote:
> On 2/10/20 3:54 PM, Paul Moore wrote:
>> On Fri, Feb 7, 2020 at 4:56 PM Paul Moore <paul(a)paul-moore.com> wrote:
>>
>> Generally speaking the only syscalls which generate a PATH record are
>> those syscalls which take a file pathname as an argument. The reason
>> why is that pathnames are notoriously transient and are only valid for
>> the instant they actually resolve to a file; in fact it is possible
>> that by the time an open(2) syscall returns the fd to the calling
>> application, the file it opened may no longer be accessible at the
>> pathname used to open the file. It really is that crazy.
>>
>> In the case of ftruncate(2) we see that the syscall doesn't take a
>> pathname argument, it takes an open file descriptor, this is why you
>> don't see a PATH record. If we compare it to a syscall which does
>> take a pathname, e.g. chown(2), we will generate a PATH record. Take
>> the example below where we use the example program found in the
>> chown(2) manpage:
>>
>> # touch /tmp/test
>> # auditctl -w /tmp/test -k path_test
>> # gcc -o chown_test -g chown_test.c
>> # ./chown_test
>> ./chown_test <owner> <file>
>> # ./chown_test nobody /tmp/test
>> # ausearch -i -k path_test
>> ----
>> type=CONFIG_CHANGE msg=audit(02/10/2020 17:50:45.251:255) : auid=root ses=5 subj
>> =unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 op=add_rule key=path_test
>> list=exit res=yes
>> ----
>> type=PROCTITLE msg=audit(02/10/2020 17:51:29.356:258) : proctitle=./chown_test n
>> obody /tmp/test
>> type=PATH msg=audit(02/10/2020 17:51:29.356:258) : item=0 name=/tmp/test inode=7
>> 0660 dev=00:21 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:obj
>> ect_r:user_tmp_t:s0 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
>> cap_frootid=0
>> type=CWD msg=audit(02/10/2020 17:51:29.356:258) : cwd=/root/tmp
>> type=SYSCALL msg=audit(02/10/2020 17:51:29.356:258) : arch=x86_64 syscall=chown
>> success=yes exit=0 a0=0x7ffc820c0603 a1=nobody a2=unset a3=0x40044e items=1 ppid
>> =1678 pid=35451 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=
>> root sgid=root fsgid=root tty=pts1 ses=5 comm=chown_test exe=/root/tmp/chown_tes
>> t subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=path_test
>>
>> ... in the example above we see that we do have a PATH record, as expected.
>>
>
> So, this is all reasonable. But why do I get this with fchown which also
> takes a file descriptor?
>
> type=PROCTITLE msg=audit(02/06/2020 10:59:30.562:59894) : proctitle=kwin
> -session 106f726361000123384967700000029380000_1548775895_794186
> type=PATH msg=audit(02/06/2020 10:59:30.562:59894) : item=0 name=(null)
> inode=595335 dev=fd:01 mode=file,600 ouid=USER ogid=USER rdev=00:00
> obj=unconfined_u:object_r:config_home_t:s0 objtype=NORMAL cap_fp=none
> cap_fi=none cap_fe=0 cap_fver=0
> type=SYSCALL msg=audit(02/06/2020 10:59:30.562:59894) : arch=x86_64
> syscall=fchown success=yes exit=0 a0=0xd a1=0x584b a2=0x584b a3=0xc items=1
> ppid=27089 pid=27152 auid=USER uid=USER gid=USER euid=USER suid=USER
> fsuid=USER egid=USER sgid=USER fsgid=USER tty=(none) ses=16 comm=kwin
> exe=/usr/bin/kwin subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> key=perm_mod
>
> It's this disparity between fchown and ftruncate that caught my attention.
First off, it is worth distinguishing between a PATH record with a
valid pathname (the chown(2) case) and a PATH record with an
invalid/NULL pathname (the fchown(2) case). At this point you
hopefully understand why those PATH records are different, and why
they sometimes have a pathname, and why sometimes they do not.
For syscalls which resolve pathnames the pathname information for the
PATH records are collected as the pathname is resolved (the only time
they are valid). When the syscall is done, the resolved pathname
information is turned into the PATH records you see.
In the case of fchown(2) there is no pathname resolution, the kernel's
fchown(2) implementation explicitly records the passed file descriptor
for reasons that Casey mentioned: it's security relevant since you are
changing the file's ownership. The ftruncate(2) syscall isn't
security relevant so there is no explicit attempt to record the file
descriptor information. This is why fchown(2) generates a pathless
PATH record, and why ftruncate(2) does not.
If you are still curious, I would suggest you take a look at the
kernel code, all the answers are there, and we could always use
another set of hands/eyes ;)
Thank you again for the detailed response. I was working with RHEL7 stig
rules like:
https://www.stigviewer.com/stig/red_hat_enterprise_linux_7/2017-12-14/fin...
which seem to imply some security relevance for ftruncate, and then noticing
that the ftruncate record didn't seem to provide any kind of useful
information at all. But I can appreciate some cargo-cult like behavior in the
security implementation realm :).
--
Orion Poplawski
Manager of NWRA Technical Systems 720-772-5637
NWRA, Boulder/CoRA Office FAX: 303-415-9702
3380 Mitchell Lane orion(a)nwra.com
Boulder, CO 80301
https://www.nwra.com/