SELinux
Contents
SELinux is a Mandatory Access Control system. It is enabled by default on some Linux systems, especially on RedHat-derivatives. SELinux prevents programs from accessing files, directories or ports unless it is configured to access those resources.
SELinux could prevent MariaDB from starting with a non-default port, or reading or writing some files (datadir, log files, configuration files...) placed in a non-default path.
Changing policy and path labels requires the policycoreutils-python package to install semanage
and audit2allow
tools.
Verifying Whether SELinix Is Enabled
To verify whether SELinux is enabled, execute the getenforce
command. For example:
getenforce
Building and Loading the Server's SELinux Policy
MariaDB Server comes with an SELinux policy that is not build or loaded by default. On many systems, the policy is installed to /usr/share/mysql/policy/selinux/mariadb-server.fc
. In order to build it and load it, execute the following:
sudo yum install selinux-policy-devel cd /usr/share/mysql/policy/selinux/ make -f /usr/share/selinux/devel/Makefile mariadb-server.pp sudo semodule -i mariadb-server.pp
Troubleshooting SELinux Issues
Temporarily Putting mysqld Into Permission Mode
When you are troubleshooting issues that you think SELinux might be causing, it can help to temporarily put mysqld_t
into permissive mode. This can be done by executing the semanage
command. For example:
semanage permissive -a mysqld_t
If that solved the problem, then it means that the current SELinux policy is the culprit. You need to adjust the SELinux policy or labels for MariaDB.
SELinux and MariaDB Path Changes
If you have a mysql error log that looks like:
130321 11:50:51 mysqld_safe Starting mysqld daemon with databases from /datadir ... 2013-03-21 11:50:52 2119 [Warning] Can't create test file /datadir/ 2013-03-21 11:50:52 2119 [Warning] Can't create test file /datadir/ ... 2013-03-21 11:50:52 2119 [ERROR] /usr/sbin/mysqld: Can't create/write to file '/datadir/boxy.pid' (Errcode: 13 - Permission denied) 2013-03-21 11:50:52 2119 [ERROR] Can't start server: can't create PID file: Permission denied 130321 11:50:52 mysqld_safe mysqld from pid file /datadir/boxy.pid ended
First be sure that the /datadir is owned by the mysql user with read write permissions for that user.
If /var/log/audit/audit.log looks something like:
type=AVC msg=audit(1363866652.030:24): avc: denied { write } for pid=2119 comm="mysqld" name="datadir" dev=dm-0 ino=394 scontext=unconfined_u:system_r:mysqld_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=dir
then you need to adjust your file system labelling so that SELinux knows this is MariaDB's datadir. Check with:
ls -ldaZ /datadir drwxr-xr-x. root root unconfined_u:object_r:var_t:s0
semanage fcontext -a -t mysqld_db_t "/datadir(/.*)?" restorecon -Rv /datadir
If you use logrotate, logrotate needs to write to the directory with its logs. Without the right SELinux permissions you might find that logrotate doesn't have the permissions to rotate the log file. Log files need the label mysqld_log_t
. It is ideal to configure MariaDB to use a non-datadir for this as two directories can't share the same label. The filesystem label can be changed to mysqld_log_t
using:
semanage fcontext -a -t mysqld_log_t "/var/log/mysql(/.*)?" restorecon -Rv /var/log/mysql
Configuration file permissions use the label mysqld_etc_t
so changing from the default will require those to be relabeled the same way.
If your directory is something else, like changing the MariaDB tmpdir to /run/shm (has serious implications if using large temp tables, this isn't a default endorsement), you can't easily change the filesystem label without affecting other programs that use /run/shm. Using the procedure below for other SELinux changes, you should end up with a module like:
MySQL_tmpfs.te:
module MySQL_tmpfs 1.0; require { type tmpfs_t; type mysqld_t; class dir { write search read remove_name open getattr add_name }; class file { write getattr read lock create unlink open }; } allow mysqld_t tmpfs_t:dir { write search read remove_name open getattr add_name }; allow mysqld_t tmpfs_t:file { write getattr read lock create unlink open }
To convert this into a loaded module perform the following:
checkmodule -M -m MySQL_tmpfs.te -o MySQL_tmpfs.mod semodule_package -m MySQL_tmpfs.mod -o MySQL_tmpfs.pp semodule -i MySQL_tmpfs.pp
SELinux and MariaDB On a Different Port
TCP and UDP ports are enabled for permission to bind too. If you are using a different port, or some Galera ports, configure SELinux to be able to use those ports:
semanage port -a -t mysqld_port_t -p tcp 3307
Other SELinux Changes
It could also be the case that a plugin or configuration usages has required a SElinux permission not thought of by the SElinux module developers.
Start by temporarily putting mysqld_t
into permissive mode:
semanage permissive -a mysqld_t
Here we record what MariaDB is doing and to create a policy to allow that (but nothing else).
- Switch SELinux to permissive mode and remove dontaudits from the policy:
semodule -DB semanage permissive -a mysqld_t
- start MariaDB
- use the generated audit log to create a policy:
grep mysqld /var/log/audit/audit.log | audit2allow -M mariadb_local semodule -i mariadb_local.pp
- Remove the permissive mode for
mysqld_t
and restore dontaudits:
setmodule -B semanage permissive -d mysqld_t
The same procedure can be used if MariaDB starts but SELinux prevents it from functioning correctly. For example, SELinux may prevent PAM plugin from authenticating users. The solution is the same — enable auditing, switch to permissive, do, whatever SELinux didn't allow you to, create a policy from the audit log.
When you discover any needed SELinux permissions, please report the needed permissions to your operating system bug tracking so all users can benefit from your work (e.g. Red Hat Bugzilla https://bugzilla.redhat.com/).