Taming SELinux Denials In Fedora 8

As many of you already know, I’m using Fedora 8 for my dedicated servers and for my workstations at home and so I’m faced with either dealing with SELinux or completely disabling it. I choose to deal with it!

This documentation is about writing local policies in order to reduce the amount of AVC Denials flooding your log file. This document can be read from beginning to end, it can also be used as a reference.

Here’s a brief definition of what SELinux is all about from the National Security Agency SELinux FAQ.

“Security-enhanced Linux (SELinux) is a reference implementation of the Flask security architecture for flexible mandatory access control. It was created to demonstrate the value of flexible mandatory access controls and how such controls could be added to an operating system. The Flask architecture has been subsequently mainstreamed into Linux and ported to several other operating systems, including Solaris, FreeBSD, and Darwin, spawning a wide range of related work. The Flask architecture provides general support for the enforcement of many kinds of mandatory access control policies, including those based on the concepts of Type EnforcementĀ®, Role-based Access Control, and Multi-level Security.”

In a nutshell, SELinux creates another form of secure computing environment, making it harder to mis-use the environment. It’s like having a suburban house with motion detectors in every corner equipped with automatic machine guns.

At this point in time, it’s common for a SELinux policy to contain bugs that can cause certain operations by applications to be blocked by SELinux. SELinux interprets these operations that aren’t part of the current policy as attacks and therefore blocks its execution to prevent any damage to the current system.

As a system administrator, your job is to write custom SELinux policies for your server so that each operation by an application is allowed by SELinux’s security engine. Writing custom SELinux policies for your applications usually means checking log files every time you load the application even after just having written a new custom SELinux policy for it. This is pretty time consuming and most system administrators would rather turn off SELinux completely instead of learning how to write custom SELinux policies for each application running in their servers.

For this documentation, we’ll be using Munin as the application that we’ll be writing custom SELinux policies for. Munin which means memory is a monitoring tool that keeps track of what your current computer is doing and saves them in a log file. It represents the information found in the log file in colourful graphs through a web interface.

First we need to install Munin.

yum install munin munin-node

Then we tell Fedora 8 to include it in the system start up, and also start to Munin now.

chkconfig --levels 235 munin-node on
/etc/init.d/munin-node start

If you have access to a GUI, then you should be alerted by SELinux telling you that it blocked an operation from an application. Double-clicking on that icon takes you to SELinux’s Troubleshooter Browser where you all the AVC Denials are listed including how many times they were blocked, their category (If known), and a summary of the AVC Denial.

For this article, the AVC Denial is SELinux is preventing find (munin_t) “read” to ./clientmqueue (mqueue_spool_t). We’ll then look at the original Raw Audit Message in the Additional Information section.

host=linux-P4RD0NM3DV9000 type=AVC msg=audit(1208360104.331:1074): avc: denied { read } for pid=8171 comm="find" name="clientmqueue" dev=dm-0 ino=15091619 scontext=system_u:system_r:munint:s0 tcontext=system_u:object_r:mqueue_spool_t:s0 tclass=dir
<!--formatted-->

What it means is that SELinux denied the operation read from the context of the application munin_t, and the context of the target object is mqueue_spool_t with the target object file dir.

For the next couple of steps in writing a custom SELinux policy, I prefer to be in CLI (Command Line Interface) instead of a GUI (Graphical User Interface).

Login to your normal user account and do the following:

su -

And login as root. I prefer this method than logging in as root first.

Make a directory called selinux/avcs in /root.

mkdir selinux
cd selinux
mkdir avcs
cd avcs

Then start up your favorite editor and make a local.te file, the te stands for Type Enforcement It will then be loaded as a policy module later. Once the file is open, type the following.

module local 1.0;

require {
type munin_t;
type mqueue_spool_t;

class dir { read } ;
}

# munin_t
allow munin_t mqueue_spool_t: dir { read };

You can re-edit the file later, so save and close the file for now. We’ll then do the following commands.

To compile the te file. Please check first if you have the checkpolicy rpm installed since it’s part of that rpm.

checkmodule -M -m -o local.mod local.te

To create the policy package.

semodule_package -o local.pp -m local.mod

To add it to the current machine’s running SELinux policy. A new module is then added with its rules into the module store.

semodule -i local.pp

You should get the same message as this one.

[root@linux-P4RD0NM3DV9000 avcs]# checkmodule -M -m -o local.mod local.te
checkmodule: loading policy configuration from local.te
checkmodule: policy configuration loaded
checkmodule: writing binary representation (version 6) to local.mod
[root@linux-P4RD0NM3DV9000 avcs]# semodule_package -o local.pp -m local.mod
[root@linux-P4RD0NM3DV9000 avcs]# semodule -i local.pp
[root@linux-P4RD0NM3DV9000 avcs]#

I suggest you to reboot your computer, just to make sure. And that’s it you’re done.

This is the final local.te after going through all of the AVC Denials.

module local 1.0;

require {
type file_t;
type hostname_exec_t;
type munin_t;
type munin_port_t;
type mqueue_spool_t;
type setfiles_t;
type sysctl_fs_t;
type sysctl_irq_t;
type tmpreaper_t;
type unconfined_tmp_t;
type var_spool_t;

class capability { kill };
class dir { getattr read remove_name rmdir setattr write } ;
class file { execute getattr read unlink write };
class sock_file { getattr };
class tcp_socket { name_bind };
}

# munin_t
allow munin_t hostname_exec_t:file { execute };
allow munin_t munin_t:capability { kill };
allow munin_t munin_port_t:tcp_socket { name_bind };
allow munin_t mqueue_spool_t:dir { read };
allow munin_t sysctl_fs_t:file { read };
allow munin_t sysctl_irq_t:dir { getattr };
allow munin_t unconfined_tmp_t:file { getattr };
allow munin_t var_spool_t:dir { read };

# setfiles_t
allow setfiles_t file_t:file { write };

# tmpreaper_t
allow tmpreaper_t file_t:dir { read remove_name rmdir setattr write };
allow tmpreaper_t file_t:file { getattr unlink };
allow tmpreaper_t file_t:sock_file { getattr };

Tags: , ,

Leave a Reply