3

I've been struggling for a couple of days with this now and have been trying to use this thread amongst other google searches to resolve it but can't seem to get it to work.

When I run this SELECT query (Ubuntu Server 15.10 & MySQL 5.6)...

SELECT column1 ,column2
FROM table 
INTO OUTFILE '/home/user/mysql_temp/file.csv';

I get this permission error...

ERROR 1 (HY000): Can't create/write to file '/home/mysql_temp/file.csv' (Errcode: 13 - Permission denied)

From my searching, I understand this to be a system permissions issue rather than a MySQL problem but I can't seem to find a solution which fixes it for me.

Checking apparmor shows that mysqld IS in enforce mode...

apparmor module is loaded.
6 profiles are loaded.
6 profiles are in enforce mode.
   /sbin/dhclient
   /usr/lib/NetworkManager/nm-dhcp-client.action
   /usr/lib/NetworkManager/nm-dhcp-helper
   /usr/lib/connman/scripts/dhclient-script
   /usr/sbin/mysqld
   /usr/sbin/tcpdump
0 profiles are in complain mode.
2 processes have profiles defined.
2 processes are in enforce mode.
   /sbin/dhclient (676) 
   /usr/sbin/mysqld (1285) 
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.

So I edited /etc/apparmor.d/usr.sbin.mysqld and added the following lines and then restarted apparmor...

/home/user/mysql_temp/ rw,
/home/user/mysql_temp/* rw,

I also changed the owner:group of mysql_temp to mysql and gave it full permissions...

sudo chown mysql:mysql mysql_temp

...

drwxrwxrwx 2 mysql   mysql       6 Apr  1 22:02 mysql_temp

After this, I still receive the same error.

Have I missed something? Misunderstood some of the instruction? Would be grateful for advice. Thanks.

Community
  • 1
  • 1
spcurtis81
  • 175
  • 2
  • 4
  • 14
  • What worked for me was accessing the my.ini file. Within that file, look for "Secure File Priv." There should be a file path which is the secure route mySql gives permissions to output the designated file. I hope this helps! For me, the file was under C:/ProgramData/mysql/mysql Server 5.7 – Scott Oct 03 '16 at 13:29

6 Answers6

0

Solution Based On; Ubuntu 20.10 with Apparmor active and MySql 8

Solution Summary and Lesson Learned: Unless you have a damn good reason not to

  1. Leave the default secure-file-priv settings alone,
  2. Give your user(s) FILE privileges in mysql,
  3. And tell apparmor to allow writing to the default directory set up by the mysql installer.

The default configuration set secure-files-priv to /var/lib/mysql-files. Left as it was, I was able to import files by placing them in that directory so long as I gave the user file privileges like so, GRANT FILE ON *.* TO myuser@host;

However, when I tried to write to that directory I got the dreaded Error Code: 1. Can't create/write to file '/var/lib/mysql-files/select_out.csv' (OS errno 13 - Permission denied). I could have solved this very easily by editing /etc/apparmor.d/usr.sbin.mysqld and changing

# Allow data files dir access
  /var/lib/mysql-files/ r,
  /var/lib/mysql-files/** rwk,

to

# Allow data files dir access
  /var/lib/mysql-files/ rw,
  /var/lib/mysql-files/** rwk,

But I didn't know about apparmor at the time, and so I fumbled around screwing up more stuff until I found @spcurtis81's post. If that's what happened to you, read on, maybe you can learn something from my journey.

Unfortunately at some point - and god only knows why - I decided to move the secure-file-priv directory to /mysql-files. This created a lot more work for me. If nothing else it taught me a lot, and gave me the opportunity to share.

I had to change the 'secure-files-priv' setting under [mysqld] section in one of .cnf files, but which, there are so damn many. I found it by doing this,

cd /
find . -name "*.cnf" -printf '%p\n' -exec  grep "\[mysqld\]" {} \;

and getting

./conf.d/mysqldump.cnf
./conf.d/mysql.cnf
./my.cnf
./debian.cnf
./mysql.conf.d/mysqld.cnf
[mysqld]
./mysql.conf.d/mysql.cnf
./mysql.cnf

so the file above the [mysqld] was the one for me. I found several references to modifying my.cnf but as it didn't already have the section in it, I went with mysqld.cnf. I also reckoned that the mysqld.cnf was for the server daemon as opposed to the user program. It worked, so it aint stupid, but perhaps a more knowledgeable person could explain the hierarchy of .cnf files.

There was no existing secure-files-priv entry for this setting so I found what seemed to be a reasonable location for it and added the following.

# Added 12/13/2020 in an attempt to relocate the secure-file-priv directory
secure-file-priv = /mysql-files

No joy. I found another reference that said that you had to specify a temp directory and so I uncommented this line from the same file.

# If MySQL is running as a replication slave, this should be
# changed. Ref https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_tmpdir
tmpdir    = /tmp

Still no joy. Then I found @spcurtis81's post here and learned about the apparmor settings. So in /etc/apparmor.d/usr.sbin.mysqld I changed

# Allow data files dir access
  /var/lib/mysql-files/ r,
  /var/lib/mysql-files/** rwk,

to

# Allow data files dir access
  /mysql-files/ rw,
  /mysql-files/** rwk,

AND still no f-ing joy!

The final step that resolved the issue: chmod -R 700 /mysql-files

When I had created the directory I set the owner to mysql and gave it 644 permissions. That seemed reasonable but added an error to my mysql error log: 'Insecure configuration for --secure-file-priv: Location is accessible to all OS users. Consider choosing a different directory.'

I don't like security warnings so I changed the permission to 600, never thinking mysql would need executable rights on a data directory. I was wrong. So, there you go.

pixemeck
  • 126
  • 1
  • 5
0

Don't forget, you have to reload apparmor.

$ sudo service apparmor reload
4b0
  • 21,981
  • 30
  • 95
  • 142
CG1022
  • 1
0

It's an directory error where you storing the data.

give the permission to the folder where data is store in your case the data store in the "mysql_temp"

use the command "$ chmod 777 mysql_temp"

Hack-Z
  • 47
  • 7
0

If mysqld is included in enforce mode, then the entries can be written in /var/log/messages when AppArmor blocks the writes/accesses.

You can edit /etc/apparmor.d/usr.sbin.mysqld and add /home/user/mysql_temp/ and /home/user/mysql_temp/* near the bottom like this:

/usr/sbin/mysqld  {  

    ...  

    /var/log/mysql/ r,  

    /var/log/mysql/* rw,  

    /var/run/mysqld/mysqld.pid w,  

    /var/run/mysqld/mysqld.sock w,  

    **/home/user/mysql_temp/ r,  

    /home/user/mysql_temp/* rw,**  

}

And then you can make AppArmor reload the profiles.

# sudo /etc/init.d/apparmor reload

WARNING: The above change will allow MySQL to read and write to the /home/user/mysql_temp/ directory.

Ole Pannier
  • 3,208
  • 9
  • 22
  • 33
0

Change ownership of the specified directory to mysql user.

chown mysql:mysql /data/data-directory
Rohit R.
  • 51
  • 5
0

the original question was writing to an outfile here:

INTO OUTFILE '/home/user/mysql_temp/file.csv';

the problem could be a mysql configuration; and not apparmor.

if you are running with systemd, look at this setting in /etc/systemd/system/mysql.service:

# Prevent accessing /home, /root and /run/user
ProtectHome=true

assuming all of the file permissions are correct, one would need to change this to false to write to the /home directory.

pRose_la
  • 194
  • 1
  • 12