实际问题

实际问题

我们的开发机器有多个用户,他们的各种站点都存储在 中/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.logausearch我看到如下错误:

----
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_thttpd_rotatelogs_exec_tvar_log_t无济于事。

我正在使用chcon命令执行此操作。

我错过了什么?

答案1

实际问题

翻译您提供的日志的第二行:

rotatelogs 进程PID 为 64617 的进程尝试在主目录,位于设备 md2 和 inode 7208961 上。访问被拒绝。

的安全上下文rotatelogs 进程是:unconfined_u:system_r:httpd_rotatelogs_t:s0

的安全上下文主目录是: system_u:object_r:home_root_t:s0

您需要允许 rotatelogs 读取主目录。允许 httpd 这样做很容易 ( setsebool -P httpd_enable_homedirs=1),但不幸的是 rotatelogs 不会从 httpd 继承其类型。更糟糕的是,rotatelogs 没有 setsebool 参数。

这还不是全部!您还需要允许 rotatelogs 一直搜索到所需目录,并允许它执行其任务所需的所有操作 —— 包括文件本身和包含它们的目录。

简而言之,您需要编写一项本地政策。

分步解决方案

在任意位置创建一个名为 的类型强制文件homelogs.te,其内容如下:

module homelogs 1.0;

require {
        type httpd_rotatelogs_t;
        type home_root_t;
        type user_home_t;
        type user_home_dir_t;
        class dir { add_name getattr open read remove_name search write };
        class file { create getattr open read rename unlink write };
}

#============= httpd_rotatelogs_t =============
allow httpd_rotatelogs_t home_root_t:dir search;
allow httpd_rotatelogs_t user_home_dir_t:dir search;
allow httpd_rotatelogs_t user_home_t:dir { add_name getattr open read remove_name search write };
allow httpd_rotatelogs_t user_home_t:file { create getattr open read rename unlink write };

现在编译它:

make -f /usr/share/selinux/devel/Makefile homelogs.pp

并安装它:

semodule -i homelogs.pp

现在 rotatelogs 应该具有在用户主目录的子目录中执行其任务所需的所有权限。


如何撰写本地政策

这是为那些想了解我如何制定本地政策的更多细节的人准备的。你有两种选择来制定政策。

audit2allow

如果您对编写本地策略完全陌生,那么一种选择是使用 包audit2allow中提供的工具policycoreutils-python来帮助您编写策略。

要修复运行 rotatelogs 时 SELinux 权限拒绝的问题,你可以运行以下命令

grep rotatelogs /var/log/audit/audit.log | audit2allow -M homelogs

将包含“rotatelogs”的审计日志输入到audit2allow。该工具将自动分析 SELinux 权限拒绝并创建类型强制文件以及编译的策略包 ( .pp) 文件。此时,您只需运行以下命令即可安装创建的策略包:

semodule -i  homelogs.pp

就这样,您就修复了所有与 rotatelogs 相关的 SELinux 问题……对吗?

这种方法的问题audit2allow无法预测需要什么权限;它只能分析哪些权限已经被拒绝。

到目前为止,只/home遇到了主目录(字面意思为 )中的搜索拒绝,因此audit2allow只能修复该问题。想想每次遇到下一个被拒绝的权限时,您将需要重新运行该工具多少次。并且根据 rotatelogs 配置,拒绝和记录特定权限可能需要数周时间。例如,rotatelogs 尝试删除旧日志文件并遇到取消链接权限拒绝需要多长时间?

Michael Hampton 在评论中指出,可以通过将 SELinux 更改为 Permissive 模式来缓解此问题:

setenforce 0

在此模式下,SELinux 将发出警告并记录操作,但不强制执行策略。这允许 rotatelogs 执行其所有任务,而 SELinux 仍会记录所有权限拒绝。然后,可以audit2allow在审计日志上运行,安装自动创建的策略,setenforce 1返回到强制模式,然后完成。

由于之前不知道可以这样使用 Permissiive 模式,我手动编写了本地策略,如下所述。不需要手动编写,但希望阅读后能有所启发。

手动创建

了解了 Type Enforcement 文件后,您可以通过手动编写来解决权限问题,防患于未然。我创建了一个 Type Enforcement 文件(带有扩展名.te)。Type Enforcement 文件位于何处并不重要。

类型执行文件有三个部分。

模块部分

module homelogs 1.0;

模块部分列出了您将使用本地策略创建的模块的名称和版本。名称应该是唯一的,否则您将替换同名的现有模块。您可以使用 检查已安装模块的名称semodule -l

require 部分

require {
        type httpd_rotatelogs_t;
        type home_root_t;
        type user_home_t;
        type user_home_dir_t;
        class dir { add_name getattr open read remove_name search write };
        class file { create getattr open read rename unlink write };
}

如上所述这里

此 [部分] 告知策略加载器在安装此模块之前系统策略中需要哪些类型、类和角色。如果任何这些字段未定义,semodule 命令将失败。

在你的情况下,rotatelogs将与几个类型。在 rotatelogs 可执行文件和所需路径的目录上运行后ls -Z,我发现需要以下类型:

  • httpd_rotatelogs_t
  • home_root_t
  • user_home_t
  • user_home_dir_t

你还需要与一些. 完整的类别及其权限列表如下这里。对于您的情况,我们将只与class file和合作class 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 home_root_t:dir search;
allow httpd_rotatelogs_t user_home_dir_t:dir search;
allow httpd_rotatelogs_t user_home_t:dir { add_name getattr open read remove_name search write };
allow httpd_rotatelogs_t user_home_t:file { create getattr open read rename unlink write };

规则部分读起来相当容易。例如:

allow httpd_rotatelogs_t user_home_t:dir { add_name getattr open read remove_name search write };

大致意思是:

允许命令使用 httpd_rotatelogs_t 类型来执行运营add_name、geattr、open、read、remove_name、search 和 write 的目录类型为 user_home_t。

请注意,每个类别都需要单独的规则,因为不同的类别具有与之相关的不同权限。

编译和安装

这是多余的,但我还是要再提一下。您需要将 Type Enforcement 文件编译成 Policy Package。运行时make,Type Enforcement 文件需要位于您当前的工作目录中。

make -f /usr/share/selinux/devel/Makefile homelogs.pp

最后,将策略包作为模块安装:

semodule -i homelogs.pp


编写自定义策略的有用资源:

答案2

无法在上面的优秀答案中添加评论,所以我必须添加一个新的“答案”:

如果由于缺少文件而无法编译新创建的模块/usr/share/selinux/devel/Makefile,请确保安装该selinux-policy-devel软件包:

yum install selinux-policy-devel

现在该文件将存在并且您可以继续其余的操作。

相关内容