我们的开发机器有多个用户,他们的各个站点都存储在/home/username/apache
. 在这些文件夹中是子文件夹,例如conf
包含虚拟主机配置、logs
包含日志、public
包含实际 Web 文件等。
我想更改日志,而不是单个日志文件:
CustomLog "/home/user/apache/domain.tld/logs/web.log" combined
我们将日志分为每日日志:
CustomLog "|/usr/sbin/rotatelogs -l /home/user/apache/domain.tld/logs/%Y%m%d_web.log 86400" combined
但是,当我放入此配置时,重新启动 apache,然后重新加载页面,同时audit.log
进入ausearch
,我看到如下错误:
----
type=SYSCALL msg=audit(06/06/2014 14:16:51.401:406272) : arch=x86_64 syscall=open success=no exit=-13(Permission denied) a0=7fff70a92460 a1=80441 a2=1b6 a3=7fff70a92110 items=0 ppid=64542 pid=64617 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=1193 comm=rotatelogs exe=/usr/sbin/rotatelogs subj=unconfined_u:system_r:httpd_rotatelogs_t:s0 key=(null)
type=AVC msg=audit(06/06/2014 14:16:51.401:406272) : avc: denied { search } for pid=64617 comm=rotatelogs name=home dev=md2 ino=7208961 scontext=unconfined_u:system_r:httpd_rotatelogs_t:s0 tcontext=system_u:object_r:home_root_t:s0 tclass=dir
我想我可以通过更改类型来解决这个问题,就像我已经解决了其他 SELinux 问题(例如允许 apache 写入文件)一样,但是在尝试了一些之后,我仍然得到上面相同的错误。我试过了httpd_log_t
,没有用。httpd_rotatelogs_exec_t
var_log_t
我正在使用chcon
命令执行此操作。
我错过了什么?
实际问题
要翻译您提供的日志的第二行:
您需要允许 rotatelogs 读取主目录。允许 httpd 这样做很容易 (
setsebool -P httpd_enable_homedirs=1
),但不幸的是,rotatelogs 没有从 httpd 继承其类型。更糟糕的是,rotatelogs 没有 setsebool 参数。这还不是全部!您还需要允许 rotatelogs 一直搜索到所需的目录,并允许它执行其任务所需的所有操作——包括文件本身和包含它们的目录。
简而言之,您需要编写本地策略。
分步解决方案
在任何地方创建一个名为 的类型强制文件
homelogs.te
,其内容如下:现在编译它:
make -f /usr/share/selinux/devel/Makefile homelogs.pp
并安装它:
semodule -i homelogs.pp
现在,rotatelogs 应该拥有在用户主目录的子目录中执行其任务所需的所有权限。
如何编写本地策略
这是为那些想要了解我如何编写本地政策的更多详细信息的人准备的。您有两个选项来编写策略。
审计2允许
如果您对编写本地策略完全不熟悉,一种选择是使用 软件包
audit2allow
中提供的工具policycoreutils-python
来帮助您编写一个。要在运行 rotatelogs 时修复 SELinux 权限拒绝,您可以运行命令
将包含“rotatelogs”的审计日志馈送到
audit2allow
. 该工具将自动分析 SELinux 权限拒绝并创建类型强制文件以及编译后的策略包 (.pp
) 文件。此时,您可以通过运行以下命令简单地安装创建的策略包:就这样,您已经修复了所有与旋转日志相关的 SELinux 问题……对吧?
这种方法的问题是
audit2allow
无法预测需要哪些权限;它只能分析已经拒绝了哪些权限。到目前为止,只
/home
遇到了主目录(字面意思)中的搜索拒绝,所以audit2allow
只会解决这个问题。想想每次遇到下一个被拒绝的权限时,您必须重新运行该工具多少次。并且根据rotatelogs 配置,拒绝和记录特定权限可能需要数周时间。例如,rotatelogs 需要多长时间才能尝试删除旧日志文件并拒绝取消链接权限?Michael Hampton 在评论中指出,可以通过将 SELinux 更改为 Permissive Mode 来缓解这个问题:
在这种模式下,SELinux 将警告并记录操作,但不会强制执行该策略。这允许 rotatelogs 执行所有任务,而 SELinux 仍然记录所有权限拒绝。然后可以
audit2allow
在审计日志上运行,安装自动创建的策略,setenforce 1
返回强制模式,然后完成。由于之前不知道可以通过这种方式使用 Permissiive 模式,因此我手动编写了本地策略,如下所述。没有必要手动完成,但希望阅读具有一定的教育意义。
手动创建
对 Type Enforcement 文件有一定的了解后,您可以通过手写来解决权限问题。我创建了一个类型强制文件(带有
.te
扩展名)。类型强制文件在哪里并不重要。类型强制文件包含三个部分。
模块部分
模块部分列出了您将使用本地策略创建的模块的名称和版本。该名称应该是唯一的,否则您将替换已存在的同名模块。您可以使用 . 检查已安装模块的名称
semodule -l
。要求部分
如此处所述:
在您的情况下,rotatelogs 将与多种类型交互。在
ls -Z
rotatelogs 可执行文件和所需路径的目录上运行后,我发现需要以下类型:httpd_rotatelogs_t
home_root_t
user_home_t
user_home_dir_t
您还需要与一些类进行交互。类及其权限的完整列表在这里。对于您的情况,我们将只使用
class file
andclass dir
。您还必须列出您将与之交互的每个类的权限。根据完整列表,我选择要求这些类和权限(有几个可能不是必需的,但我在允许方面犯了错误):班级目录:
add_name
- 将文件添加到目录getattr
- 获取文件的文件属性,例如访问模式。(例如 stat,一些 ioctl ......)open
- 打开一个目录read
- 读取文件内容remove_name
- 从目录中删除文件search
- 搜索访问write
- 一般写权限;添加或删除所需类文件:
create
-getattr
- 获取文件的文件属性,例如访问模式。(例如 stat,一些 ioctl ......)open
- 打开一个文件read
- 读取文件内容rename
- 重命名文件unlink
- 删除硬链接(删除)write
- 写入文件规则部分
规则部分读起来相当容易。例如:
allow httpd_rotatelogs_t user_home_t:dir { add_name getattr open read remove_name search write };
大致意思是:
请注意,每个类都需要一个单独的规则,因为不同的类将具有与其关联的不同权限。
编译安装
这是多余的,但我会再次提到它。您需要将类型强制文件编译到策略包中。运行
make
时,类型强制文件需要在您当前的工作目录中。make -f /usr/share/selinux/devel/Makefile homelogs.pp
最后,将策略包安装为模块:
semodule -i homelogs.pp
编写自定义策略的有用资源:
无法在上面的优秀答案中添加评论,所以我必须添加一个新的“答案”:
如果由于缺少
/usr/share/selinux/devel/Makefile
文件而无法编译新制作的模块,请确保安装该selinux-policy-devel
软件包:yum install selinux-policy-devel
现在该文件将存在,您可以继续进行其余操作。