Working with SElinux booleans

SElinux booleans are on/off switches that can be easily disabled or enabled if required. I’ll try to show you in this article how you can interact with SElinux booleans on a Linux machine. Note that for this demonstration I will be using a CentOS 6 Virtual Machine.

To view a detailed list of available selinux booleans you would type getsebool -a command, which will display something like:

selinux

SElinux booleans

Let’s say you have an Apache web server and you want to check out what SElinux modules are available within the OS. Since there are a lot of available booleans, we can refine this search by typing getsebool -a | grep httpd to list only the available Apache booleans. Each boolean has a distinctive role within the OS and will enable a particular access for the Apache web server. I’m not going to discuss about them now but, you can read further here.

To enable a SElinux boolean simply execute the  setsebool boolean_name on/off command, just like in the following example:

setsebool httpd_enable_homedirs on

Using the same command but with the off switch will disable the boolean:

setsebool httpd_enable_homedirs off

Note that these changes are not persistent unless you use the -P parameter and will disappear once you reboot the machine. So this is how you would make a persistent change:

setsebool -P httpd_mod_auth_pam on
setsebool -P httpd_enable_homedirs on
The first time you activate a boolean that’s not enabled by default, a file named booleans.local will be created on the machine, which contains the enabled booleans. You can view the content of this file in  /etc/selinux/targeted/modules/active/booleans.local .Note that if you modify this file manually,  you will not create any changes to SElinux since this file is created for users and it’s not used to enable/disable booleans:
boolean

Selinux enabled booleans file

SElinux will normally point you to the right command if there are some issues logged in the audit file. Literally, it will actually show you the exact command that you have to execute to fix your issues. So if you have any booleans that needs enabled, just check out the audit or the messages files to get an idea on what needs to be configured.

Advertisements

How to create SElinux policy

SElinux is a security mechanism introduced in Linux OS as an extra security layer. There are probably many things to be mentioned about selinux so I’m not going to discuss about the main concepts that make up selinux such as labeling and targeting. I’ll show you in this article how to create a new selinux policy (also known as module) and install it on a machine.

You can check the selinux status by typing getenforce without any parameters. You can then use setenforce 0 command to change it to permissive or setenforce 1 again to enforce it:

selinux

selinux status

All SElinux messages are logged in /var/log/audit/audit.log, you can inspect this file to determine what applications are blocked from interacting with the Operating System. /var/log/messages is another location in which you can find useful information about selinux logs. As you will probably see, the log file contains a bunch of information that is hard to read, you can use the audit2allow -w -a command to display a more friendlier output. This command will parse the audit.log file ( -a parameter) and then will create a friendlier output (-w parameter) that looks something like:

SElinux

selinux policy

In SElinux context all log messages are named AVC so you will see them everywhere in the audit log file.

You can view all SElinux  rejected accesses using the audit2allow -a command:

SElinux

How to create SElinux policy

This command can also be used to parse the log file then create a module that can be imported by SElinux to allow access. Execute audit2allow -a -M module_name to create a new SElinux module. I’ve named mine zabbixdiamond and placed it in my home directory. The command will create two files, one with .pp and another one with .te extension:

audit2allow -a -M zabbixdiamond

SElinux module

selinux policy files

You can view the content of the selinux module by executing cat zabbixdiamond.te command. As you can see from the image below, the module contains all the rules that are needed by SElinux to allow this particular AVC :

How to create SElinux policy

how to create selinux module

All that’s left now is to install the module using the following command: semodule -i zabbixdiamond.pp. If you encounter an error saying something that “global requirements are not met” it means that SElinux already has a module with a similar name installed on the machine so you’ll need to change its name:

How to create SElinux policy

how to install selinux module

In this case you will have to restart the procedure and create a new SElinux module with a different name. To check what modules are installed on the server use semodule -l. You can expand this command and search for a particular SElinux module with semodule -l | grep zabbixdiamond . In this way you also verify if a SElinux module has been successfully loaded in the OS.

Execute again audit2allow -a and see if the AVCs are now allowed in SElinux:

How to create SElinux policy

audit2allow command with selinux

That’s about it for this article folks, hope it will serve you well in creating SElinux policies. Wish you all the best!

How to manually create SElinux modules

I’ve shown you in a previous article how to create and install SElinux modules automatically using audit2allow -a. Usually, any needed policies can be configured using audit2allow command or by enabling a SElinux Boolean module. You can check out the status of boolean modules by typing:

getsebool -a

seli1

Configure new SElinux module

You can try to generate a SElinux module using audit2allow -a -M module_name. This command will parse the /var/log/audit/audit.log file and determine what actions are denied by SElinux. If you use the audit2allow -a -M zabbixdiamond command it will automatically create a SElinux module (.pp extension) and a SElinux configuration file (.te extension). Note that I’ve encountered situations in which this method was inefficient because not all permissions were added correctly by SElinux.

I’ve seen situations in which after importing a SElinux a module that was generated using audit2allow command, the following command would be logged in the audit log file:

“Unknown – would be allowed by active policy
Possible mismatch between this policy and the one under which the audit message was generated.

Possible mismatch between current in-memory boolean settings vs. permanent ones”

This error occurs because SElinux does not create the module with all the needed permissions .

If you receive this error, you’ll need to edit the .te file and add the missing permissions:

Edit the .te file (zabbixdiamond.te) using vim:

module zabbixdiamond 1.0;

require {
type unconfined_t;
type semanage_t;
type init_t;
type system_cronjob_t;
type syslogd_t;
type rpm_t;
type postfix_smtpd_t;
type system_dbusd_t;
type snmpd_t;
type smtp_port_t;
type proc_net_t;
type http_port_t;
type ntpd_t;
type kernel_t;
type postfix_master_t;
type auditd_t;
type httpd_t;
type audisp_t;
type irqbalance_t;
type inetd_t;
type udev_t;
type postfix_pickup_t;
type sshd_t;
type crond_t;
type getty_t;
type nrpe_t;
type postfix_qmgr_t;
type zabbix_agent_t;
class tcp_socket name_connect;
class file { read getattr open ioctl };
}

#============= zabbix_agent_t ======================
allow zabbix_agent_t audisp_t:file { read getattr open };
allow zabbix_agent_t auditd_t:file { read getattr open };
allow zabbix_agent_t crond_t:file { read getattr open };
allow zabbix_agent_t getty_t:file { read getattr open };
allow zabbix_agent_t http_port_t:tcp_socket name_connect;
allow zabbix_agent_t httpd_t:file { read getattr open };
allow zabbix_agent_t inetd_t:file { read getattr open };
allow zabbix_agent_t init_t:file { read getattr open };
allow zabbix_agent_t irqbalance_t:file { read getattr open };
allow zabbix_agent_t kernel_t:file { read getattr open };
allow zabbix_agent_t nrpe_t:file { read getattr open };
allow zabbix_agent_t ntpd_t:file { read getattr open };
allow zabbix_agent_t postfix_master_t:file { read getattr open };
allow zabbix_agent_t postfix_pickup_t:file { read getattr open };
allow zabbix_agent_t postfix_qmgr_t:file { read getattr open };
allow zabbix_agent_t postfix_smtpd_t:file { read getattr open };
allow zabbix_agent_t proc_net_t:file { read getattr open ioctl };
allow zabbix_agent_t rpm_t:file { read getattr open };
allow zabbix_agent_t semanage_t:file {read getattr open };
allow zabbix_agent_t smtp_port_t:tcp_socket name_connect;
allow zabbix_agent_t snmpd_t:file { read getattr open };
allow zabbix_agent_t sshd_t:file { read getattr open };
allow zabbix_agent_t syslogd_t:file { read getattr open };
allow zabbix_agent_t system_cronjob_t:file { getattr open };
allow zabbix_agent_t system_dbusd_t:file { read getattr open };
allow zabbix_agent_t udev_t:file { read getattr open };
allow zabbix_agent_t unconfined_t:file { read getattr open };

#==================================================

Once all permissions have been added, save and close the file.

Use the following command to verify if the module syntax is correct

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

Any syntax error will be reported by the checkmodule command, just like in the following example:

checkmodule: loading policy configuration from zabbixdiamond.te
zabbixdiamond.te:55:ERROR ‘syntax error’ at token ‘{‘ on line 55:
allow zabbix_agent_t proc_net_t:file { read getattr open ioctl};
allow zabbix_agent_t rpm_t:file getattr { read getattr open };

Note that all permissions must be defined in the class file { read getattr open ioctl }; section, elsewhere you will receive an error something similar with:

checkmodule: loading policy configuration from zabbixdiamond.te
zabbixdiamond.te:54:ERROR ‘permission ioctl is not defined for class file’ at token ‘;’ on line 54:
allow zabbix_agent_t proc_net_t:file { read getattr open ioctl};
allow zabbix_agent_t postfix_smtpd_t:file { read getattr open };

If the module verification has been successfully completed, you will be informed that the policy configuration has been loaded:

checkmodule: loading policy configuration from zabbixdiamond.te
checkmodule: policy configuration loaded
checkmodule: writing binary representation (version 10) to zabbixdiamond.mod

The module .pp file will be created in the location the where the checkmodule command was executed.

Now it’s time to package the module file using the following command:

semodule_package -o zabbixdiamond.pp -m zabbixdiamond.mod

Finally you have to execute semodule -i zabbixdiamond.pp command to install the newly created SElinux module.

Once the module has been created, execute audit2allow -a and see if all missing policies are allowed by SElinux. Using the semodule -l command you can view all installed SElinux modules, check out if the newly created module is listed here. You can also verify the audit file to see if any other denies are seen.