Logwatch output to NFS with SELinux

430 words, 3 minutes.

As part of a log consolidation exercise I’d decided to try and put logwatch output into Splunk, to later produce some succinct analysis.

The easiest way for me to achieve this was to send the logwatch output to a file on a NFS volume.

However, the host in question has SELinux enabled (quite deliberately). Often the answer to SELinux problems is ‘disable it’, but that’s not the proper answer! And really, I could do with learning it.

First off, analysis of the audit log told me what I suspected - it was SELinux preventing the write:

# ausearch -m avc --start today 
time->Sun Jan 12 03:14:05 2014
type=SYSCALL msg=audit(1389496445.113:2441932): arch=c000003e syscall=2 success=no exit=-13 a0=2817680 a1=441 a2=1b6 a3=37ba71dd40 items=0 ppid=32511 pid=32517 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=31998 comm="logwatch" exe="/usr/bin/perl" subj=system_u:system_r:logwatch_t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1389496445.113:2441932): avc:  denied  { write } for  pid=32517 comm="logwatch" name="host" dev=0:1c ino=1834908 scontext=system_u:system_r:logwatch_t:s0-s0:c0.c1023 tcontext=system_u:object_r:nfs_t:s0 tclass=dir

The key bits to note here are the scontext, the tcontext and the tclass - source and target contexts, and the target class.

Essentially, the target directory was of ’type’ nfs_t, and the source process was of logwatch_t type.

Let’s check the default SELinux policy for this combination:

# sesearch -t nfs_t -s logwatch_t -c dir -A
   allow logwatch_t nfs_t : dir { ioctl read getattr lock search open } ; 

Ah - so logwatch_t cannot write to a dir of type nfs_t. That’ll be our problem.

We can fix this by writing a custom module. The easy way is to take our denied log entry and pipe it through audit2allow. First off, let’s do that, but output to a text file for review, before we implement the rule:

# ausearch -m avc --start today | audit2allow -m logwatch_nfs_write -o logwatch_nfs_write.te

(we could just have easily grep’d for the offending line in the actual audit.log file)

Now review the output file to make sure it’s all sensible:

module logwatch_nfs_write 1.0;
require {
        type logwatch_t;
        type nfs_t;
        class dir write;
#============= logwatch_t ==============
#!!!! The source type 'logwatch_t' can write to a 'dir' of the following types:
# var_lock_t, tmp_t, logwatch_cache_t, logwatch_tmp_t, var_run_t
allow logwatch_t nfs_t:dir write;

OK, looks sensible. So now we can compile it, and insert into the running modules:

# ausearch -m avc --start today | audit2allow -M logwatch_nfs_write
# semodule -i logwatch_nfs_write.pp

And check it’s in memory:

# semodule -l | grep logwa
logwatch_nfs_write      1.0

Now when I run logwatch the file is created. Sorted.

There are some examples in /usr/share/selinux/devel, on CentOS at least, that could be useful for writing modules from scratch.