Managing Data Directory Permissions with SELinux and AppArmor

Understanding the Problem

When you move MySQL's data directory (usually /var/lib/mysql), the MySQL server process needs permission to read and write to the new location. SELinux and AppArmor enforce mandatory access control, meaning that even if the MySQL user has file system permissions, these security modules can still block access.

Identifying Your Security Module

First, determine which security module your system uses:

  • SELinux: Run getenforce. If it returns Enforcing or Permissive, SELinux is active

  • AppArmor: Run apparmor_status. If it shows loaded profiles, AppArmor is active

Configuring SELinux

If SELinux is active, follow these steps:

  1. Identify the Current SELinux Context of the Data Directory:

    ls -ldZ /var/lib/mysql # Replace with the original location if you haven't moved it yet.

    The output will look something like this:

    drwxr-xr-x. mysql mysql system_u:object_r:mysqld_db_t:s0 /var/lib/mysql

    The important part is system_u:object_r:mysqld_db_t:s0. This is the SELinux context. We need to apply this context to the new directory.

  2. Apply the Correct SELinux Context:

    semanage fcontext -a -t mysqld_db_t "/new/path/to/mysql_data(/.*)?"
    restorecon -Rv /new/path/to/mysql_data
    • semanage fcontext -a -t mysqld_db_t "/new/path/to/mysql_data(/.*)?": This command adds a file context rule for the new directory and all its subdirectories. mysqld_db_t is the type for MySQL data files

    • restorecon -Rv /new/path/to/mysql_data: This applies the new context to the directory

  3. Update MySQL Configuration: Edit the MySQL configuration file (usually /etc/my.cnf or /etc/mysql/my.cnf) and change the datadir directive: (Skip this step if configuration already changed)

    [mysqld]
    datadir=/new/path/to/mysql_data
  4. Restart MySQL:

    systemctl restart mysqld

Troubleshooting SELinux

  • Check SELinux Logs: If you still have issues, check the SELinux audit logs: ausearch -m avc -ts recent. This will show any denied operations. Use audit2allow to create custom SELinux rules if necessary (use with caution)

  • Set SELinux to Permissive (For Testing Only): setenforce 0. If MySQL works in permissive mode, you know it's an SELinux issue. Remember to set it back to enforcing mode: setenforce 1

Configuring AppArmor

If AppArmor is active, follow these steps:

  1. Edit the AppArmor Profile: The MySQL AppArmor profile is usually located at /etc/apparmor.d/usr.sbin.mysqld. Create a backup first:

    cp /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/usr.sbin.mysqld.bak

    Edit /etc/apparmor.d/usr.sbin.mysqld and add rules for the new data directory. Look for lines like this:

    /var/lib/mysql/ r,
    /var/lib/mysql/** rwk,

    Replace /var/lib/mysql with your new path:

    /new/path/to/mysql_data/ r,
    /new/path/to/mysql_data/** rwk,

    The ** means all subdirectories and files. r is for read, w is for write, and k is for locking.

  2. Reload the AppArmor Profile:

    systemctl reload apparmor
  3. Update MySQL Configuration: Edit the MySQL configuration file (usually /etc/my.cnf or /etc/mysql/my.cnf) and change the datadir directive:

    [mysqld]
    datadir=/new/path/to/mysql_data
  4. Restart MySQL:

    systemctl restart mysql

Troubleshooting AppArmor

  • Check AppArmor Logs: Use dmesg | grep apparmor or check /var/log/syslog or /var/log/audit/audit.log for AppArmor denials

  • AppArmor in Complain Mode (For Testing Only): You can put the MySQL profile in complain mode to see what it would have denied without actually blocking it: aa-complain /usr/sbin/mysqld. After testing, put it back into enforce mode: aa-enforce /usr/sbin/mysqld

Last updated

Was this helpful?