为什么 selinux 策略适用于从 cronjobs 运行的命令(例如:logrotate),但不适用于直接从命令行运行的命令?

为什么 selinux 策略适用于从 cronjobs 运行的命令(例如:logrotate),但不适用于直接从命令行运行的命令?

为什么 selinux 策略适用于从 cronjobs 运行的命令(例如:logrotate),但不适用于直接从命令行运行的命令?

当我从命令行手动运行 logrotate 时,它​​工作得很好。但是当它从 cronjob 运行时,我在audit.log 中收到一个错误,提醒我 selinux 阻止访问 www 等。

这是为什么?我怎样才能模拟它从 cronjob 运行来测试?

答案1

cron运行时logrotate,SELinux 将其限制为 logrotate_t“类型”。该“类型”被限制不能修改其他文件类型(也称为“逃脱限制”)。

什么时候运行 logrotate,您(很可能)从“无限制”类型开始,这意味着它所说的 -logrotate允许进程修改文件。您可能还想logrotate重新启动或向进程发送信号(例如,通过 postrotate);该活动也可能受到 SELinux 的限制。

我的建议是告诉 SELinux 允许(“允许”) logrotate_t 类型逃脱限制,方法是:

semanage permissive -a logrotate_t

这样做是一个温和的解决方案,介于两者之间关闭 SELinux并微调策略,以准确地允许您需要的限制逃脱(也许使用自定义标签)。要恢复此更改,请使用semanage permissive -d logrotate_t.

模拟 cron 启动进程的最佳方法是将作业放入 cron 中。另外,我知道runcon,虽然我没能成功使用它。

答案2

只是在@JeffSchaller 的好答案的基础上添加关于具体问题的内容:

我怎样才能模拟它从 cronjob 运行来测试?

我可以分享一个可行的替代方案,无需从 cronjob 运行测试命令。

首先,可能值得一提的是一个微妙的细节:

在传统的非 SELinux 环境中,当您以 root 身份(有效 UID = 0)操作时,您通常可以自由切换到您喜欢的任何其他 UID,以“获得”该 UID 的限制。

这与 SELinux 的上下文完全不同:成为 root(有效 UID = 0)通常确实会将您置于“不受限制”的上下文中,但不会自动允许您自由切换到其他上下文。您更需要一个明确的 SELinux 策略规则来授予“无限制”上下文执行特定“转换”操作的许可。安装此类规则后,该runcon命令将成功将您置于该上下文中。

实际上,对于您的情况,您可能需要一个 SELinux 策略,例如简单的:

allow unconfined_t crond_t:process transition;

(假设是您的 守护进程运行的crond_tSELinux 域)crond

完整模块的编译和安装规则是:

module unconfined-trans-crond 1.0;

require {
        type unconfined_t;
        type crond_t;
        class process transition;
}

allow unconfined_t crond_t:process transition;

编译并安装该模块后,可以使用runcon 目标crond_tunconfined_t。例如:

# id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# runcon $(ps -q $(pgrep crond) -o context --no-header) sh
# id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:crond_t:s0
#

另请注意,您不需要 UID 0 即可使用runcon,您“只”需要允许从当前 SELinux 上下文转换到目标 SELinux 上下文的正确策略规则。

事实上,我通常以 root 身份运行来测试守护进程(例如crond)的完整命令是:

runuser $(ps -q $(pgrep crond) -o user --no-header) -c 'runcon $(ps -q $(pgrep crond) -o context --no-header) /bin/bash'

crond它提供了一个以的用户及其 SELinux 上下文运行的 shell 。

要在完成测试后撤消该策略,只需删除自定义模块即可。

这当然没有考虑到可能的其他限制,例如不同的命名空间视图、资源限制 (ulimits)、cgroup 或 Linux 功能。这些将需要按顺序运行其他命令才能重新创建这些附加限制,除非 PAM 配置runuser在某种程度上与为您重新创建它们时保持一致。

华泰

答案3

受到 @Jeff_Schaller 和 @LL3 的答案的启发,以下是为此过程提出正确的 sepolicy 模块的方法:

:; sudo semanage permissive -a logrotate_t
# turn off selinux for logrotate temporarily to allow the logrotate command to go through, while still logging the denied messages in audit.log

:; sudo runcon -u system_u -r system_r -t logrotate_t logrotate -f /etc/logrotate.conf
:; sudo semanage permissive -d logrotate_t # re-enable selinux

:; sudo grep denied /var/log/audit/audit.log | audit2allow -M logrotate
# create a selinux policy based on the denied messages

:; sudo semodule -i logrotate.pp

的内容logrotate.te最终看起来像这样

module logrotate 1.0;

require {
        type initrc_exec_t;
        type default_t;
        type policykit_t;
        type logrotate_t;
        class dbus send_msg;
        class file { create getattr ioctl open read setattr unlink write };
        class dir { add_name read remove_name write };
        class service reload;
}

#============= logrotate_t ==============
allow logrotate_t default_t:dir { add_name read remove_name write };

#!!!! WARNING: 'default_t' is a base type.
allow logrotate_t default_t:file { create getattr ioctl open read setattr unlink write };
allow logrotate_t initrc_exec_t:service reload;
allow logrotate_t policykit_t:dbus send_msg;

答案4

我对 SElinux 没有深入的了解,我不确定它是否与其他答案相同。这是我的做法:在目录内。 crontab 的 semanage fcontext -a -t 'myCronTab' logrotate_exec_t这使得 cronjob 和 处于logrotate相同的上下文中,因此它应该就像是通过命令行执行的。

相关内容