Is auditing ftruncate useful?

Orion Poplawski orion at nwra.com
Wed Feb 12 21:00:16 UTC 2020


On 2/11/20 5:58 AM, Paul Moore wrote:
> On Mon, Feb 10, 2020 at 6:05 PM Orion Poplawski <orion at 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 at 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/finding/V-72133

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 at nwra.com
Boulder, CO 80301                 https://www.nwra.com/

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3799 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://listman.redhat.com/archives/linux-audit/attachments/20200212/f87d07e5/attachment.p7s>


More information about the Linux-audit mailing list