Yesterday I was asked by one of our old customers to help solving very interesting problem – he put some php files outside of apache DocumentRoot on his server and the apache could not access the files, producing very interesting lines into apache default error_log
1 |
"[warn-phpd] mmap cache can't open file /home/conf.php - permission denied (pid XXX of XXX)" |
To my surprise I’ve never seen such an error message in my life, and I have spent 19 years dealing with this. I was pretty sure I could identify the source of the problem just by looking at it. The customer claimed that he spend 3 hours googling for the solution without finding one and even getting any better understanding of what the problem is.
The system was basic CentOS 5.10 with everything installed from the official repositories. Config file /home/conf.php permissions and ownership allowed read access to everybody so there was no obvious reason why it would throw this strange error. Even the source of the message was a mystery – what is this “phpd” and why I’ve never heard of it? Doesn’t look like some process or even file on the system. PHP was used as regular mod_php so there were no surprises there. Nor there was any exotic or popular PHP opcode caching modules installed.
There is only one more usual suspect – SELinux, while very useful in high security environments in my opinion is is also quite useless and even harmful in high load webhosting situation. And while well known for granularity and flexibility of the configuration is also very well known for difficulty of troubleshooting.
It quite easy to check from terminal ssh connection
1 2 |
$sudo getenforce Enforcing |
SELinux is turned on. But does it really preventing access to the file in question? Let’s check the log
1 2 |
$sudo grep httpd /var/log/audit/audit.log type=AVC msg=audit(1412012148.975:24304): avc: denied { read } for pid=17315 comm="httpd" name="conf.php" dev=dm-3 ino=78512640 scontext=root:system_r:httpd_t:s0 tcontext=system_u:object_r:home_root_t:s0 tclass=file |
In order to verify our findings we can try to disable SELinux
1 2 3 |
$sudo setenforce 0 $sudo getenforce Permissive |
After restart apache works properly – there is no problems with reading /home/conf.php and strange error messages gone.
How we are still running SELinux code even though it doesn’t ask it still examining every system event against SELinux configuration and writes sizable logs.
In order to disable SELinux once and for good we will have to modify 2 files and reboot (unfortunately there is no other way).
-
In /etc/sysconfig/selinux we need to change parameter SELINUX, so the file will look like this
12345678910# This file controls the state of SELinux on the system.# SELINUX= can take one of these three values:# enforcing - SELinux security policy is enforced.# permissive - SELinux prints warnings instead of enforcing.# disabled - No SELinux policy is loaded.SELINUX=disabled# SELINUXTYPE= can take one of these two values:# targeted - Targeted processes are protected,# mls - Multi Level Security protection.SELINUXTYPE=targeted - In GRUB config /boot/grub/menu.lst we will have to add option “selinux=0” to the kernel line to it will be turned off from the very boot time.
For example
12345678default=0timeout=5splashimage=(hd0,0)/grub/splash.xpm.gzhiddenmenutitle CentOS (2.6.32-431.5.1.el6.x86_64)root (hd0,0)kernel /vmlinuz-2.6.32-431.5.1.el6.x86_64 ro root=UUID=0ee347b6-b5ec-4c0d-b6a6-0155ef8507fe nomodeset rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_NO_LVM KEYBOARDTYPE=pc KEYTABLE=be-latin1 rd_NO_DM rhgb quiet selinux=0initrd /initramfs-2.6.32-431.5.1.el6.x86_64.imgNow after the reboot SElinux will be off your back until you decide that you really require it for your server operation.
very excellent 🙂