On Tue, 2007-07-03 at 07:57 -0400, Stephen Smalley wrote:
On Tue, 2007-07-03 at 00:23 +0100, Matthew Booth wrote:
> On Tue, 2007-07-03 at 10:48 +1200, Darryl Dixon - Winterhouse Consulting
> wrote:
> > Hi Matt,
> >
> > Thank you for your very thorough response. What you say about not being
> > able to audit 'write()' is worrying to me. The problem with auditing
write
> > by inference from open(), is that one doesn't know *when* the file was
> > written, or even if it really ever was at all (eg, was data written
> > continuously from open() to close(), or only sporadically over the course
> > of hours or days?). Auditing for actual alterations is definitely
> > something that we need to be able to track. Assuming for a moment that we
> > have beefy enough hardware ( heh ), can the path be extracted from write()
> > as with your example for open() above? My assumption would have been that
> > CWD reflected only where the exe was launched from, and not necessarily
> > where the write()-en file was located...
>
> Well, you can audit write(). The question is whether you can handle the
> resulting data volume.
>
> read() and write() don't generate a PATH record. The only time at which
> a path is relevant is at the time the file is opened. Once the file is
> opened, it can have zero or more paths, which can all change without
> affecting the open file. An open file is genuinely divorced from its
> path.
>
> That said, it's *not* divorced from its filesystem, which I understand
> is what you're really looking for. Unfortunately that information
> doesn't appear to live on its own in the audit trail, and it's not
> available to filter on for these calls. This would leave you having to
> audit all read() and write() calls and filtering them in
> post-processing. I doubt this would be a practical solution.
Another option might be to audit based on SELinux type, if the files in
question can have a different type than the rest of the files. A
SELinux audit message on write would generate an AVC_PATH record.
Example:
$ vi myaudit.te
policy_module(myaudit, 1.0)
require {
attribute domain;
type etc_t;
}
auditallow domain etc_t:file write;
:q
$ make -f /usr/share/selinux/devel/Makefile myaudit.pp
$ su
# /usr/sbin/semodule -i myaudit.pp
# vi /etc/fstab
:wq
Audit log contains:
type=AVC msg=audit(1183463480.620:6351): avc: granted { write } for pid=13773
comm="vi" name="fstab" dev=dm-0 ino=1280187
scontext=user_u:system_r:unconfined_t:s0 tcontext=user_u:object_r:etc_t:s0 tclass=file
type=SYSCALL msg=audit(1183463480.620:6351): arch=40000003 syscall=4 success=yes exit=767
a0=3 a1=9047510 a2=2ff a3=2ff items=0 ppid=13662 pid=13773 auid=4204 uid=0 gid=0 euid=0
suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 comm="vi" exe="/bin/vi"
subj=user_u:system_r:unconfined_t:s0 key=(null)
type=AVC_PATH msg=audit(1183463480.620:6351): path="/etc/fstab"
One caveat though - auditing of write() won't catch all possible ways of
modifying the file data, e.g. one could mmap() the file with MAP_SHARED
and then write to the memory, followed by msync or munmap.
--
Stephen Smalley
National Security Agency