I recently had a issue getting MySQL to read a specific database. Each time I tried to manually query a table in the database, I received the following error message:

ERROR 1018 (HY000): Can't read dir of './default/' (errno: 13)

I’ve seen this message before as it means that there is a permissions issue. I checked the ownerships and permissions, and everything seemed to be in order.

The only thing special about this database is that I have it symlinked to another partition. This has always worked in the past, so I was stumped.

The problem turned out to be that Ubuntu has AppArmor. This software sets up rules that prevent software from gaining access to different areas of the file system. In my case, AppArmor was preventing read and write access to the actual location of my database files.

The solution was quite easy: First, I added the path that I wanted MySQL to have access to in the AppArmor configuration file for MySQL. Second, I restarted the apparmor service. Here’s the technical details:

  1. On my system, the configuration file that controls MySQL permissions through AppArmor are located at /etc/apparmor.d/usr.sbin.mysqld. The following shows the contents of the file as it now exists:
    # vim:syntax=apparmor
    # Last Modified: Tue Jun 19 17:37:30 2007
    #include 
    
    /usr/sbin/mysqld {
      #include
      #include
      #include
      #include
      #include 
    
      capability dac_override,
      capability sys_resource,
      capability setgid,
      capability setuid,
    
      network tcp,
    
      /etc/hosts.allow r,
      /etc/hosts.deny r,
    
      /etc/mysql/*.pem r,
      /etc/mysql/conf.d/ r,
      /etc/mysql/conf.d/* r,
      /etc/mysql/my.cnf r,
      /usr/sbin/mysqld mr,
      /usr/share/mysql/** r,
      /var/log/mysql.log rw,
      /var/log/mysql.err rw,
      /var/lib/mysql/ r,
      /var/lib/mysql/** rwk,
      /var/log/mysql/ r,
      /var/log/mysql/* rw,
      /var/run/mysqld/mysqld.pid w,
      /var/run/mysqld/mysqld.sock w,
      /home/sites/default/mysql/ rw,
      /home/sites/default/mysql/* rw,
    
      /sys/devices/system/cpu/ r,
    }

    The two lines in bold show what I added to the configuation. The first line gives read and write access to the directory itself while the second gives read and write access to the files contained in the directory.

  2. After saving the configuration changes, I simply needed to restart the AppArmor daemon. I did this with the following command:
    [chris@rommie ~]$ sudo service apparmor restart
     * Reloading AppArmor profiles
    Skipping profile in /etc/apparmor.d/disable: usr.bin.firefox