我在 Debian squeeze 系统上设置了 SELinux,该系统运行 Joomla 网站。Joomla PHP 代码需要对某些缓存目录具有写访问权限。
/var/log/messages 文件包含如下条目:
Dec 31 10:26:16 s0022 kernel: [ 2116.423199] type=1400 audit(1356945976.634:14831):
avc: denied { write } for pid=1886 comm="apache2" name="_system" dev=xvda3
ino=790893 scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:httpd_t:s0 tclass=dir
Dec 31 10:26:16 s0022 kernel: [ 2116.447613] type=1400 audit(1356945976.658:14837):
avc: denied { write } for pid=1886 comm="apache2" name="mod_mainmenu" dev=xvda3
ino=791346 scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:httpd_t:s0 tclass=dir
对应于 inode 值的目录可由 apache2(以 wwwrun 身份运行)写入。缓存文件是在 SELinux 关闭时创建的,而不是在 SELinux 激活时创建的。但是,这些目录的路径与 Debian Squeeze 的默认 DocumentRoot 不同。
# ls -ldZ cache cache/_system cache/mod_mainmenu
drwxrwxr-x. 5 wwwrun www unconfined_u:object_r:httpd_t:s0 4096 Dec 29 23:13 cache
drwxrwxr-x. 2 wwwrun www unconfined_u:object_r:httpd_t:s0 4096 Dec 30 19:31 cache/mod_mainmenu
drwxrwxr-x. 2 wwwrun www unconfined_u:object_r:httpd_t:s0 4096 Dec 30 19:31 cache/_system
我也尝试启用写入相关的布尔标志,但这也无济于事:
# getsebool -a | grep httpd
allow_httpd_anon_write --> on
allow_httpd_mod_auth_pam --> off
allow_httpd_sys_script_anon_write --> on
allow_httpd_user_script_anon_write --> on
httpd_builtin_scripting --> off
httpd_can_network_connect --> off
httpd_can_network_connect_db --> on
httpd_can_network_relay --> off
httpd_can_sendmail --> off
httpd_dbus_avahi --> off
httpd_enable_cgi --> off
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> on
httpd_ssi_exec --> off
httpd_tty_comm --> off
httpd_unified --> off
httpd_use_cifs --> off
httpd_use_gpg --> off
httpd_use_nfs --> off
我曾使用 audit2allow 创建可加载模块,以便为其他守护进程(例如 rotatelog)启用写访问,但我认为在这种情况下这不是可行的方法。httpd 的模块已经存在,如果可以避免,我不想以任何方式触碰它。
我只是在寻找一种方法,让 apache2 / php / Joomla 在我的特定 DocumentRoot 内的特定目录中写入,而不授予对任何其他内容的写入权限。请提供建议。
答案1
缓存目录由各种不同类型的用户使用,如您之前提到的,apache 用户、php 用户,甚至可能是单独的 Joomla 用户(如果您使用 mod_fcgid)。对于这样的目录,存在类型public_content_rw_t
上下文。这使得它对于所有相关服务都是可写的,并且(因为它“只是”一个带有临时文件的缓存目录)不应该造成太大的安全风险。所以我建议使用命令将类型更改为公共类型
chcon -R -t public_content_rw_t /path/to/wwwroot/cache
答案2
您需要告诉 SELinux 缓存位置的类型是httpd_cache_t
:
# semanage fcontext -a -t 'httpd_cache_t' '/path/to/wwwroot/cache(/.*)?'
# restorecon -Rvvv /path/to/wwwroot/cache