SELinux拦截PHP mkdir()失败,因安全上下文类型不匹配导致write被拒;需用semanage永久设置httpd_sys_rw_content_t类型并restorecon应用,而非仅改chmod/chown。

PHP用mkdir()创建目录失败,日志里出现avc: denied { write },基本可以确定是SELinux在拦截——它和传统文件权限无关,即使chown、chmod全对,照样报错。
确认SELinux是否启用并处于生效状态
先执行命令验证:
-
getenforce—— 返回 Enforcing 才说明SELinux正在主动限制 -
sestatus—— 查看完整状态,重点关注 Current mode 和 Policy from config file
如果返回 Disabled,那问题不在SELinux;如果是 Permissive,它只记录不拦截,也不会导致mkdir()失败。
查清PHP进程实际运行路径与所需上下文类型
ThinkPHP的runtime/、上传临时目录upload_tmp_dir这类需PHP写入的路径,不能沿用只读内容的默认上下文(如httpd_sys_content_t),而必须用可写类型:
立即学习“PHP免费学习笔记(深入)”;
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 常见可写类型:
httpd_sys_rw_content_t(Apache/PHP-FPM常用)、svirt_sandbox_file_t(容器场景) - 查已定义类型:
seinfo -t | grep httpd或sesearch -A -s httpd_t -t httpd_sys_rw_content_t -c dir -p write - 确认PHP实际写入路径:
ps aux | grep php-fpm或检查php-fpm.conf中的user和group,再结合upload_tmp_dir或runtime的绝对路径
永久配置SELinux上下文(推荐)
不要用chcon临时改,重启后失效;要用semanage注册规则+restorecon应用:
- 添加路径规则:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/path/to/your/dir(/.*)?"(注意末尾(/.*)?表示递归生效) - 立即应用规则:
sudo restorecon -Rv /path/to/your/dir - 验证结果:
ls -Z /path/to/your/dir应显示类似system_u:object_r:httpd_sys_rw_content_t:s0
若semanage未安装,在CentOS/RHEL系运行sudo yum install policycoreutils-python-utils;Ubuntu默认不用SELinux,但若启用了,需装policycoreutils-python。
排查其他可能干扰项
SELinux只是常见原因,别漏掉这些:
-
挂载选项限制:目标目录在NAS、NTFS或FAT分区?检查
mount输出,确认是否带fmask/dmask或umask=022等导致www-data实际无写权 -
AppArmor(Ubuntu常见):查
dmesg | grep apparmor,若有denied记录,需调整/etc/apparmor.d/对应配置 -
PHP自身限制:确认没被
open_basedir或disable_functions=mkdir拦住;upload_tmp_dir路径需PHP进程用户(如www-data)可写且归属正确,否则静默失败
不复杂但容易忽略


















