Zabbix, varnishstat, and SELinux

SHARE
April 25, 2016

audit2allow to the Rescue!

Fortunately, SELinux is also pretty good about logging exactly what happened.  If you examine /var/log/audit/audit.log you’ll see entries like these:

type=AVC msg=audit(1461552223.200:10692): avc: denied { read } for pid=21525 comm="varnishstat" name="_.vsm" dev="dm-0" ino=264030 scontext=system_u:system_r:zabbix_agent_t:s0 tcontext=system_u:object_r:varnishd_var_lib_t:s0 tclass=file
type=SYSCALL msg=audit(1461552223.200:10692): arch=c000003e syscall=2 success=no exit=-13 a0=7fe75188f2d0 a1=0 a2=0 a3=7ffcf1c25f40 items=0 ppid=21524 pid=21525 auid=4294967295 uid=997 gid=995 euid=997 suid=997 fsuid=997 egid=995 sgid=995 fsgid=995 tty=(none) ses=4294967295 comm="varnishstat" exe="/usr/bin/varnishstat" subj=system_u:system_r:zabbix_agent_t:s0 key=(null)
type=AVC msg=audit(1461552224.272:10693): avc: denied { read } for pid=21529 comm="varnishstat" name="_.vsm" dev="dm-0" ino=264030 scontext=system_u:system_r:zabbix_agent_t:s0 tcontext=system_u:object_r:varnishd_var_lib_t:s0 tclass=file
type=SYSCALL msg=audit(1461552224.272:10693): arch=c000003e syscall=2 success=no exit=-13 a0=7f2bd2d932d0 a1=0 a2=0 a3=7ffdd37c0870 items=0 ppid=21528 pid=21529 auid=4294967295 uid=997 gid=995 euid=997 suid=997 fsuid=997 egid=995 sgid=995 fsgid=995 tty=(none) ses=4294967295 comm="varnishstat" exe="/usr/bin/varnishstat" subj=system_u:system_r:zabbix_agent_t:s0 key=(null)
type=AVC msg=audit(1461552225.314:10694): avc: denied { read } for pid=21533 comm="varnishstat" name="_.vsm" dev="dm-0" ino=264030 scontext=system_u:system_r:zabbix_agent_t:s0 tcontext=system_u:object_r:varnishd_var_lib_t:s0 tclass=file

It’s a bunch of gobbledook, right?  With a bit effort, we can see what’s being denied — read on the _.vsm file, by the varnishstat command.  But how do we fix it?

This is where SELinux can get very complicated.  Policy files are a magic all their own, and I’ve not really delved very deeply into it.  There’s a lot I don’t know.  Fortunately, though, the audit2allow tool solves this problem neatly.

Running the tool (with the -m option to provide a policy module name) and feeding it the relevant part of the audit log results in the following output:

[root@varnish-01 audit]# grep zabbix audit.log | audit2allow -m fio-zabbix-agent > fio-zabbix-agent.te
[root@varnish-01 audit]# cat fio-zabbix-agent.te

module fio-zabbix-agent 1.0;

require {
 type zabbix_agent_t;
 type varnishd_var_lib_t;
 class process setrlimit;
 class file { read open };
}

#============= zabbix_agent_t ==============

allow zabbix_agent_t self:process setrlimit;

allow zabbix_agent_t varnishd_var_lib_t:file { read open };

The content is that of a simple SELinux security policy.  This can then be fed to the various SELinux tools to generate and install the actual policy module.  Simple, right?

Note that you should examine this output carefully before using it to generate and install a policy.  The grep is indiscriminate, and you might generate policies you didn’t intend to.  Don’t be afraid to prune stuff that you don’t think belongs; the worst thing that will likely happen is that you’ll have to start over.

Compiling an SELinux Policy

The output of audit2allow is an SELinux policy source file.  These are (for reasons unknown to me) usually stored in files with a .te extension.  Don’t forget to verify what you see there before saving it; if it doesn’t look right, then it probably isn’t, and you run SELinux for security purposes, right?  Be sure you’re happy with the policy.

Once you have your source file (fio-zabbix-agent.te in our case, matching the module name we gave to audit2allow’s -m option), the next thing you need to do is compile it down into an installable package.  This isn’t terribly difficult, but nor is it obvious to the uninitiated.  Googling around will eventually lead you to the answer, but finding the whys and wherefores ( without wading through a bunch of unnecessary technical nonsense) is a bit more difficult.

This process is accomplished in three steps:

  1. Install the required tools.  In RHEL 7.x, these are contained in the checkpolicy, policycoreutils, and policycoreutils-python packages.  Use yum to install them, and you’re set; no configuration required.
  2. Compile the text policy down to a binary representation.
  3. Package the binary representation in a package that the SELinux semodule tool can load.

We’ll skip over installing the packages; you already know how to do that, right?  Instead, we’ll skip straight to compiling the module to binary.  This process is fairly straightforward:

GTU:LAB steve@blog-01:~$ checkmodule -M -m -o fio-zabbix-agent.mod fio-zabbix-agent.te
checkmodule: loading policy configuration from fio-zabbix-agent.te
checkmodule: policy configuration loaded
checkmodule: writing binary representation (version 17) to fio-zabbix-agent.mod

And that’s it.  This step will give you the fio-zabbix-agent.mod file, which is the binary representation of the policy.  With that done, we can move on to step 3:

GTU:LAB steve@blog-01:~$ semodule_package -o fio-zabbix-agent.pp -m fio-zabbix-agent.mod

Done.  You now have the fio-zabbix-agent.pp file.

Now all you have to do is install it.