Sunday, November 17, 2013

mysqld and SELinux

I have had the most unfortunate chance to discover how SELinux is enabled by default on CentOS 6.4 and it is mostly likely to have been enabled by default on Red Hat's 6.4. Ok, maybe I lied, I knew SELinux was enabled by default, I just happened to forget that it was enabled by default.

After having installed mysql-server
# yum install mysql-server

And making certain changes to the /etc/my.cnf, and in my case it was the changing of the datadir from the default /var/lib/mysql to /mysqldatadir

This was what I did when I created the custom directory /mysqldatadir
# mkdir -p /mysqldatadir/mysql
# chown -R mysql:mysql /mysqldatadir
# cp -pR /var/lib/mysql/mysql/*

After of which I tried to start mysqld
# service mysqld start
Initializing MySQL database:  Installing MySQL system tables...
131116 14:04:52 [Warning] Can't create test file /mysqldatadir/jupiter.lower-test
131116 14:04:52 [Warning] Can't create test file /mysqldatadir/jupiter.lower-test
ERROR: 1005  Can't create table 'db' (errno: 13)
131116 14:04:52 [ERROR] Aborting

131116 14:04:52 [Note] /usr/libexec/mysqld: Shutdown complete


Installation of system tables failed!  Examine the logs in
/mysqldatadir for more information.

You can try to start the mysqld daemon with:

    shell> /usr/libexec/mysqld --skip-grant &

and use the command line tool /usr/bin/mysql
to connect to the mysql database and look at the grant tables:

    shell> /usr/bin/mysql -u root mysql
    mysql> show tables

Try 'mysqld --help' if you have problems with paths.  Using --log
gives you a log in /mysqldatadir that may be helpful.

Please consult the MySQL manual section
'Problems running mysql_install_db', and the manual section that
describes problems on your OS.  Another information source are the
MySQL email archives available at http://lists.mysql.com/.

Please check all of the above before mailing us!  And remember, if
you do mail us, you MUST use the /usr/bin/mysqlbug script!

                                                           [FAILED]

Of course, that was when I checked and found out that getenforce was set to Enforced.
# getenforce
Enforcing

Tailed the /var/log/mysqld.log and these were what I could see (and read)
# tail -100 /var/log/mysqld.log
131116 14:06:24 mysqld_safe Starting mysqld daemon with databases from /mysqldatadir
131116 14:06:24 [Warning] Can't create test file /mysqldatadir/jupiter.lower-test
131116 14:06:24 [Warning] Can't create test file /mysqldatadir/jupiter.lower-test
/usr/libexec/mysqld: Table 'mysql.plugin' doesn't exist
131116 14:06:24 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
131116 14:06:24  InnoDB: Initializing buffer pool, size = 8.0M
131116 14:06:24  InnoDB: Completed initialization of buffer pool
131116 14:06:24  InnoDB: Operating system error number 13 in a file operation.
InnoDB: The error means mysqld does not have the access rights to
InnoDB: the directory.
InnoDB: File name ./ibdata1
InnoDB: File operation call: 'create'.
InnoDB: Cannot continue operation.
131116 14:06:24 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended

Tailed the /var/audit/audit.log for any denied entry with regards to mysql
# tail -100 /var/log/audit/audit.log | grep -i mysql
type=AVC msg=audit(1384628936.756:96): avc:  denied  { write } for  pid=2157 comm="mysqld" name="mysqldatadir" dev=dm-0 ino=3301 scontext=unconfined_u:system_r:mysqld_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=dir

type=SYSCALL msg=audit(1384628936.756:96): arch=c000003e syscall=2 success=no exit=-13 a0=7fff98ce2560 a1=42 a2=1b6 a3=7fff98ce2020 items=0 ppid=2055 pid=2157 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=5 comm="mysqld" exe="/usr/libexec/mysqld" subj=unconfined_u:system_r:mysqld_t:s0 key=(null)

type=AVC msg=audit(1384628936.757:97): avc:  denied  { write } for  pid=2157 comm="mysqld" name="mysqldatadir" dev=dm-0 ino=3301 scontext=unconfined_u:system_r:mysqld_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=dir

type=SYSCALL msg=audit(1384628936.757:97): arch=c000003e syscall=2 success=no exit=-13 a0=7fff98ce2560 a1=42 a2=1b6 a3=fffffffffffffffd items=0 ppid=2055 pid=2157 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=5 comm="mysqld" exe="/usr/libexec/mysqld" subj=unconfined_u:system_r:mysqld_t:s0 key=(null)

type=AVC msg=audit(1384628936.768:98): avc:  denied  { write } for  pid=2157 comm="mysqld" name="mysqldatadir" dev=dm-0 ino=3301 scontext=unconfined_u:system_r:mysqld_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=dir
type=SYSCALL msg=audit(1384628936.768:98): arch=c000003e syscall=2 success=no exit=-13 a0=7fff98cdf4a0 a1=c2 a2=1b0 a3=0 items=0 ppid=2055 pid=2157 auid=0 uid=27 gid=27 euid=27 suid=27 fsuid=27 egid=27 sgid=27 fsgid=27 tty=pts2 ses=5 comm="mysqld" exe="/usr/libexec/mysqld" subj=unconfined_u:system_r:mysqld_t:s0 key=(null)

When I tried my hands on the command semanage (or it's full path /usr/sbin/semanage)
# semanage
-bash: semanage: command not found

Aha! So semanage was not installed, so which package did I have to install in order to get semanage?
# yum whatprovides */semanage

So it looks like I have to install policycoreutils-python in order to be able to use semanage 
# yum install policycoreutils-python

Before I did anything a quick check on the directory /mysqldatadir to check on properties (plus SELinux context, if there was any)
# ls -lZ /mysqldatadir
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 mysql

To fix it, or at least to make mysqld to be able to use the directory /mysqldatadir as it's datadir (as defined in the /etc/my.cnf)
# semanage fcontext -a -t mysqld_db_t "/mysqldatadir(/.*)?"
# restorecon -Rv /mysqldatadir

Start up mysql, and voila!
# service mysqld start
Starting mysqld:                                           [  OK  ]

No comments: