2

I'm trying to access an SQLite file on a CentOS7 box using PHP and the PDO library. I was getting read-only errors just like this question - https://stackoverflow.com/questions/3319112/sqlite-read-only-database

And per that question, the answer was to disable SELinux. That's fine for development, but for a production system I'd like to keep SELinux enabled.

How do I leave SELinux enabled, without getting read-only errors on the SQLite file?

(Note: The answers in that question that relate to it don't seem to be CentOS 7 compatible).

Edit: tail -f /var/log/audit/audit.log

type=AVC msg=audit(1543600144.088:1845): avc: denied { write } for pid=13968 comm="httpd" name="html" dev="dm-0" ino=50632493 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=dir type=SYSCALL msg=audit(1543600144.088:1845): arch=c000003e syscall=2 success=no exit=-13 a0=5567d0b40859 a1=80042 a2=1ff a3=5567d0b40859 items=0 ppid=13674 pid=13968 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null) type=PROCTITLE msg=audit(1543600144.088:1845): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44

2 Answers2

4

By default PHP (which runs under the httpd_t domain) is not allowed to write files in most locations on the system, other than temporary directories.

You can set a specific file to be writable by changing its context to httpd_sys_rw_content_t. For example, to change the context temporarily:

chcon -t httpd_sys_rw_content_t /var/lib/myapp/database.sqlite

To make this permanent, you need to set a permanent file context matching the file, so that it will always be labeled this way. You do this with semanage fcontext.

semanage fcontext -a -t httpd_sys_rw_content_t /var/lib/myapp/database.sqlite
Michael Hampton
  • 252,907
2

So, from a combination of trial and error, and help from Michael's answer + comments and these:

https://stackoverflow.com/a/41132426

https://stackoverflow.com/questions/3319112/sqlite-read-only-database

The solution is these two lines (assuming the file is in /var/www/html

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html(/.*)?" restorecon -v /var/www/html

There are caveats:

  • The first line MUST have the path in quote marks or you'll get bash: syntax error near unexpected token ('

  • You must also do it to the entire directory, not just the file. Which is what the weird bit in brackets does.

(Unfortunately I lack the rep to make helpful comments about this in the above linked questions. Or even to vote up/down the right/wrong answers.)