As I wrote in my last blog port, I’ve been enabling selinux on some webservers. Last week I updated the Idera CDP agent on one server to support backup and restore of MySQL via the CDP agent. The backup is successful without any issues. Since this integrated MySQL backup was new functionality, I also wanted to test the restore. The restore did not work with selinux enabled. There were a ton of error messages in the audit.log, actually too much to paste in this blog post. I’ve attached the file with error messages cdp-mysql.

To fix the problem I’ve created multiple selinux policies, after the first 4 tries new deny messages appeared in the audit.log. After the fifth version of the policy the restore finished without any error in the log and the database that I dropped and I tried to restore was available and accessible for the sites.

To create the working policy I did the following. I copied the messages that I attached into a separate file (cdp-mysql.se) and used the following command to create a selinux policy:


audit2allow -i cdp-mysql.se -M cdp-mysql

This creates a couple of files (cdp-mysql.pp and cdp-mysql.te) in the current working directory. The cdp-mysql.te contains the plain text policy. The cdp-mysql.pp file can be used to import the selinux policy:


semodule -i cdp-mysql.pp

This activates the cronolog selinux policy that contains the configuration listed below. After this module is activated cronolog is allowed to create directories under the log directory.

module cdp-mysql 1.0;

require {
type bin_t;
type fixed_disk_device_t;
type mysqld_t;
type port_t;
type var_lib_t;
class sock_file { create unlink getattr };
class tcp_socket name_bind;
class chr_file { read write };
class file { write getattr read lock open append };
}

#============= mysqld_t ==============
allow mysqld_t bin_t:file append;
allow mysqld_t fixed_disk_device_t:chr_file { read write };
#!!!! This avc can be allowed using the boolean 'allow_ypbind'

allow mysqld_t port_t:tcp_socket name_bind;
#!!!! The source type 'mysqld_t' can write to a 'file' of the following types:
# mysqld_db_t, hugetlbfs_t, mysqld_tmp_t, mysqld_log_t, mysqld_var_run_t, root_t

allow mysqld_t var_lib_t:file { read write getattr open lock };
allow mysqld_t var_lib_t:sock_file { create unlink getattr };

For those who want to use it I’ve attaced the cdp-mysql.pp module. Make sure to test the md5 checksum (44ec3ec35db17e0adab38ad0ba1fac10 cdp-mysql.pp). You can also recreate the module with the file containing the errors from the audit.log

In the last couple of weeks I’ve started enabling selinux in enforcing mode on my webservers. Besides some expected problems, I encountered a problem with cronolog when I enabled selinux. There was no way that cronolog wanted to create the needed directories. Usually we run cronolog to create separate “Year” and “Month” directories and in every “Month” directory a separate directory and file for each day.

When I started apache with the cronolog log configuration, the following error appeared in the global apache error_log:

piped log program '/usr/sbin/cronolog /var/log/httpd/yyy.xxx.nl/%Y/%m/%d/access_log' failed unexpectedly
/var/log/httpd/wpdev.redbee.nl/2013: Permission denied
piped log program '/usr/sbin/cronolog /var/log/httpd/yyy.xxx.nl/%Y/%m/%d/access_log' failed unexpectedly

There was no year “2013” directory created in the top level log directory /var/log/httpd/yyy.xxx.nl/
As cronolog never gives any problems in that area and file rights were configured correctly, I suspected selinux. And indeed this was the problem.

In /var/log/audit/audit.log the following errors where logged:

type=AVC msg=audit(1361309216.029:25603): avc: denied { create } for pid=10047 comm="cronolog" name="2013" scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_log_t:s0 tclass=dir
type=SYSCALL msg=audit(1361309216.029:25603): arch=c000003e syscall=83 success=no exit=-13 a0=7fff5ebbf050 a1=1fd a2=ffffffffffffffa8 a3=322f6c6e2e656562 items=0 ppid=9699 pid=10047 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=175 comm="cronolog" exe="/usr/sbin/cronolog" subj=unconfined_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(1361309235.635:25604): avc: denied { create } for pid=10048 comm="cronolog" name="2013" scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_log_t:s0 tclass=dir
type=SYSCALL msg=audit(1361309235.635:25604): arch=c000003e syscall=83 success=no exit=-13 a0=7fff4cc1efa0 a1=1fd a2=ffffffffffffffa8 a3=322f6c6e2e656562 items=0 ppid=9699 pid=10048 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=175 comm="cronolog" exe="/usr/sbin/cronolog" subj=unconfined_u:system_r:httpd_t:s0 key=(null)

I copied these messages into a separate file (crono.se) and used the following command to create a selinux policy:


audit2allow -i /home/rogierm/crono.se -M crono

This creates a couple of files (crono.pp and crono.te) in the current working directory. The crono.te contains the plain text policy. The crono.pp file can be used to import the selinux policy:


semodule -i crono.pp

This activates the cronolog selinux policy that contains the configuration listed below. After this module is activated cronolog is allowed to create directories under the log directory.


module crono 1.0;

require {
type httpd_log_t;
type httpd_t;
class dir create;
}

#============= httpd_t ==============
allow httpd_t httpd_log_t:dir create;