Decoding arguments passed to system calls

Matthew Booth mbooth at redhat.com
Mon Jul 2 22:27:36 UTC 2007


On Tue, 2007-07-03 at 09:46 +1200, Darryl Dixon - Winterhouse Consulting
wrote:
> Scenario:
> A very large filesystem with potentially millions of files in an ad-hoc,
> unordered directory structure. The requirement is to be able to audit any
> action on any file in this filesystem (moves, adds, changes, deletes,
> etc). In auditfs terms, there is a requirement to have a 'watch' on every
> single file (millions of files), and on any new file that is added.
> 
> Hypothetical solution:
> Clearly, scanning the filesystem with `find` and adding calling auditctl
> with the appropriate arguments to generate a watch on every singly file is
> totally infeasible (find takes almost an hour to run, and in the meantime
> stuff is potentially changing...). Instead, I envision it would make
> better sense to simply audit every call to write(), open(), rename(), etc,
> and then filter backwards from there with ausearch and a filter based on
> the path. On Solaris with BSM, this is possible. My problem is that this
> doesn't seem possible with the Linux Audit subsystem, as the arguments to
> the system calls are not decoded (eg, the audit records for write()
> include only an opaque filehandle and pointer to the written data, etc).

This is entirely feasible, with the exception that you probably don't
want to audit write() calls generally. That would be a truly insane
amount of traffic. A highly effective heuristic is to look at the
arguments to the open() system call. If the file was opened for write
(a1 | 1 == 1 || a1 | 2 == 2), then assume that the file was altered.

Take the following example:

type=SYSCALL msg=audit(1183414428.656:2779): arch=40000003 syscall=5
success=yes exit=3 a0=91d4088 a1=8000 a2=0 a3=8000 items
=1 ppid=16166 pid=16270 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0
egid=0 sgid=0 fsgid=0 tty=pts2 comm="vi" exe="/bin/vi" sub
j=user_u:system_r:unconfined_t:s0 key=(null)

type=CWD msg=audit(1183414428.656:2779):  cwd="/root"

type=PATH msg=audit(1183414428.656:2779): item=0 name="install.log"
inode=720898 dev=fd:00 mode=0100644 ouid=0 ogid=0 rdev=00
:00 obj=root:object_r:user_home_t:s0

You can tell the filesystem from the dev field of the PATH record:
[mbooth at mbooth ~]$ ls -l /dev/mapper/vg_local-root 
brw-rw---- 1 root disk 253, 0 Jul  2 19:53 /dev/mapper/vg_local-root

253, 0 == fd:00

You can tell it was opened for read, because the last 2 bits of a1 in
the SYSCALL record are 00. I guess doing this automatically is the crux
of your question. For ease of path handling, you're also going to want a
solution to the absolute path question.

As an aside, adding the rules you mention above with a standard audit
configuration is likely to kill your system as soon as you put load on
it. The principal reason for this is the frequent flushing of the log
file. If integrity of the audit trail isn't that important, tone down
the flushing on the audit log and you'll find that it can sustain pretty
intense throughput. If you need both integrity and performance, the best
solution I've come up with is to send audit records to a remote host via
syslog in real time over a network which we trust not to drop packets,
and not write anything to disk.

Matt
-- 
Matthew Booth, RHCA, RHCSS
Red Hat, Global Professional Services

M:       +44 (0)7977 267231
GPG ID:  D33C3490
GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
URL: <http://listman.redhat.com/archives/linux-audit/attachments/20070702/d25c24c2/attachment.sig>


More information about the Linux-audit mailing list