"SELinux and nagios plugins”

I decided to write my first blog about SELinux. I want to show people how easy it can be to work with SELinux, create you own SELinux policy, and to cooperate with us on improving policy. Did I write “us”? I should mention I work with Dan Walsh on SELinux solution in Red Hat.

Let's learn more about SELinux :^)

A while back, we got a bug on using the check_disk nagios plugin with SELinux in Fedora 12. Here is the AVC:

avc: denied {getattr } for pid=23360 comm="check_disk" path="/dev/sdb1" dev=tmpfs ino=3658 scontext=system_u:system_r:nrpe_t:s0 tcontext=system_u:object_r:fixed_disk_device_t:s0 tclass=blk_file

The plugin was executed this way:
$ /usr/lib64/nagios/plugins/check_nrpe -H localhost -c check_smart_sda

Note: every plugin was running in the same nrpe_t domain. If we added the ability for the nrpe_t domain to read fixed_disk_device_t, this would allow ALL plugins to read every disk on the system. We really did not want to do this. So I wrote a policy for just the check_disk plugins allowing it to read fixed disk.

But after that we got other bugs related with different nagios plugins, requiring additional accesses to system resources. We needed a more general solution how to confine each plugin separately.

We sorted individual plugins by groups (services, system, checkdisk, unconfined) according to the plugins functionality. For each group we wrote an initial policy. Each policy creates a new SELinux domain and file type for the nagios plugin.

Domain typeSELinux file type for Executable
nagios_services_plugin_tnagios_services_plugin_exec_t
nagios_system_plugin_tnagios_system_plugin_exec_t
nagios_checkdisk_plugin_tnagios_checkdisk_plugin_exec_t
nagios_unconfined_plugin_tnagios_unconfined_plugin_exec_t

Now that we have the policy and SELinux Types, how should we use them?

As Dan Walsh has written many times:

"SELinux is all about labeling"

We need to set the proper label for the plugin. For example, we label the check_users plugin as nagios_system_plugin_exec_t. When the nagios or nrpe daemons running as nrpe_t execute a plugin labeled nagios_system_plugin_exec_t, the policy has a transiton rule like the following:

nagios_t -> nagios_system_plugin_exec_t -> nagios_system_plugin_t

As of selinux-policy-3.6.32-69.fc12 we have setup the default nagios plugin labels. You can check the labels using:

# ls -Z /usr/lib/nagios/plugins/check_*

I shouldn't forget to mention, that domains nagios_services_plugin_t, nagios_system_plugin_t, nagios_checkdisk_plugin_t run as permissive domains. This means while SELinux access ckecks are performed for these domains, they are not enforced. The kernel allows the access and reports it as an AVC denial. We can push out a new policy as permissive domain and simply collect AVC messages. Users don't have to switch to permissive mode globally and they can stay in the enforcing mode.

If you have a nagios plugin that you just do not want SELinux to interfere with its access, you can set its label to nagios_unconfined_plugin_exec_t, and SELinux will give this plugin unconfined access.

How can you help with the nagious plugin policy.

Use the standard plugin policy which Fedora ships and report any avc messages as a bug. You can fill a new bugzilla on it or send me an email with your /var/log/audit/audit.log file.

How can I stop the AVC messages?

1. You could add the selected label for your plugin using chcon:

Probably you will get a lot of AVC messages. Of course you can use audit2allow for creating the local policy for your plugin:

# grep avc /var/log/audit/audit.log | audit2allow -M myplugin
# semodule -i myplugin.pp

But that could be dangerous because ou would be allowing all plugins labeled nagios_system_plugin_exec_t this access.

2. You could consider to use nagios_plugin_unconfined_t domain for your plugin, but you would get no SELinux protections then.

# chcon -t nagios_plugin_unconfined_exec_t /usr/lib/nagios/plugins/your_plugin

3. You could create your own policy for your plugin.

* You can create the initial policy for your plugin by creating a file called myplugin.te, with the following contents

# cat myplugin.te
policy_module(myplugin, 1.0)

# creates nagios_myplugin_plugin_exec_t for executable
# and nagios_system_plugin_t for domain
nagios_plugin_template(myplugin)

permissive nagios_myplugin_plugin_t;


* Create a file called myplugin.fc

# cat myplugn.fc
/usr/lib(64)?/nagios/plugins/your_plugin -- gen_context(system_u:object_r:nagios_myplugin_plugin_exec_t,s0)

* Compile the policy and install it

# make -f /usr/share/selinux/devel/Makefile
# semodule -i myplugin.pp

* Set the labeling

# restorecon -R -v / usr/lib/nagios/plugins/your_plugin

* Now you are ready to test you plugin, it will run as the nagios_myplugin_plugin_t domain.
Run your plugin and collect the AVC message. Use audit2allow on the AVC messages to add these allow rules to your policy te file mypolicy.te

# grep myplugin /var/log/audit/audit.log | audit2allow -R >> myplugin.te

* Recompile and reinstall module

# make -f /usr/share/selinux/devel/Makefile
# semodule -i myplugin.pp

That's it. I hope people will play with the nagios plugins and SELinux and upstream their policy so we can all benefit. It is always a good idea to ask people to review your policy.