8.2. 为自定义应用程序创建并强制 SELinux 策略
您可以通过 SELinux 限制应用程序,来提高主机系统和用户数据的安全性。因为每个应用程序都有特定的要求,因此根据您的用例,为创建限制一个简单守护进程的 SELinux 策略修改这个流程示例。
先决条件
-
selinux-policy-devel
软件包及其依赖项已安装在您的系统上。
步骤
在本例中,准备一个简单的守护进程,它将打开
/var/log/messages
文件进行写入:创建一个新文件,然后在您选择的文本编辑器中打开:
$ vi mydaemon.c
插入以下代码:
#include <unistd.h> #include <stdio.h> FILE *f; int main(void) { while(1) { f = fopen("/var/log/messages","w"); sleep(5); fclose(f); } }
编译文件:
$ gcc -o mydaemon mydaemon.c
为您的守护进程创建一个
systemd
单元文件:$ vi mydaemon.service [Unit] Description=Simple testing daemon [Service] Type=simple ExecStart=/usr/local/bin/mydaemon [Install] WantedBy=multi-user.target
安装并启动守护进程:
# cp mydaemon /usr/local/bin/ # cp mydaemon.service /usr/lib/systemd/system # systemctl start mydaemon # systemctl status mydaemon ● mydaemon.service - Simple testing daemon Loaded: loaded (/usr/lib/systemd/system/mydaemon.service; disabled; vendor preset: disabled) Active: active (running) since Sat 2020-05-23 16:56:01 CEST; 19s ago Main PID: 4117 (mydaemon) Tasks: 1 Memory: 148.0K CGroup: /system.slice/mydaemon.service └─4117 /usr/local/bin/mydaemon May 23 16:56:01 localhost.localdomain systemd[1]: Started Simple testing daemon.
检查新守护进程是否没有被 SELinux 限制:
$ ps -efZ | grep mydaemon system_u:system_r:unconfined_service_t:s0 root 4117 1 0 16:56 ? 00:00:00 /usr/local/bin/mydaemon
为守护进程生成自定义策略:
$ sepolicy generate --init /usr/local/bin/mydaemon Created the following files: /home/example.user/mysepol/mydaemon.te # Type Enforcement file /home/example.user/mysepol/mydaemon.if # Interface file /home/example.user/mysepol/mydaemon.fc # File Contexts file /home/example.user/mysepol/mydaemon_selinux.spec # Spec file /home/example.user/mysepol/mydaemon.sh # Setup Script
使用上一命令创建的设置脚本使用新策略模块重建系统策略:
# ./mydaemon.sh Building and Loading Policy + make -f /usr/share/selinux/devel/Makefile mydaemon.pp Compiling targeted mydaemon module Creating targeted mydaemon.pp policy package rm tmp/mydaemon.mod.fc tmp/mydaemon.mod + /usr/sbin/semodule -i mydaemon.pp ...
请注意,设置脚本使用
restorecon
命令重新标记文件系统的对应部分:restorecon -v /usr/local/bin/mydaemon /usr/lib/systemd/system
重启守护进程,检查它现在被 SELinux 限制:
# systemctl restart mydaemon $ ps -efZ | grep mydaemon system_u:system_r:mydaemon_t:s0 root 8150 1 0 17:18 ? 00:00:00 /usr/local/bin/mydaemon
由于守护进程现在受 SELinux 限制,SELinux 也阻止它访问
/var/log/messages
。显示对应的拒绝信息:# ausearch -m AVC -ts recent ... type=AVC msg=audit(1590247112.719:5935): avc: denied { open } for pid=8150 comm="mydaemon" path="/var/log/messages" dev="dm-0" ino=2430831 scontext=system_u:system_r:mydaemon_t:s0 tcontext=unconfined_u:object_r:var_log_t:s0 tclass=file permissive=1 ...
您还可以使用
sealert
工具获取更多信息:$ sealert -l "*" SELinux is preventing mydaemon from open access on the file /var/log/messages. ***** Plugin catchall (100. confidence) suggests ************************** If you believe that mydaemon should be allowed open access on the messages file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # ausearch -c 'mydaemon' --raw | audit2allow -M my-mydaemon # semodule -X 300 -i my-mydaemon.pp Additional Information: Source Context system_u:system_r:mydaemon_t:s0 Target Context unconfined_u:object_r:var_log_t:s0 Target Objects /var/log/messages [ file ] Source mydaemon …
使用
audit2allow
工具推荐更改:$ ausearch -m AVC -ts recent | audit2allow -R require { type mydaemon_t; } #============= mydaemon_t ============== logging_write_generic_logs(mydaemon_t)
因为
audit2allow
建议的规则在某些情况下可能不正确,所以只使用其输出的一部分来查找对应的策略接口。使用macro-expander
工具检查logging_write_generic_logs(mydaemon_t)
宏,以查看宏提供的所有允许规则:$ macro-expander "logging_write_generic_logs(mydaemon_t)" allow mydaemon_t var_t:dir { getattr search open }; allow mydaemon_t var_log_t:dir { getattr search open read lock ioctl }; allow mydaemon_t var_log_t:dir { getattr search open }; allow mydaemon_t var_log_t:file { open { getattr write append lock ioctl } }; allow mydaemon_t var_log_t:dir { getattr search open }; allow mydaemon_t var_log_t:lnk_file { getattr read };
在这种情况下,您可以使用推荐的接口,因为它只提供对日志文件及其父目录的读写访问。在您的类型强制文件中添加对应的规则:
$ echo "logging_write_generic_logs(mydaemon_t)" >> mydaemon.te
另外,您可以添加这个规则而不是使用接口:
$ echo "allow mydaemon_t var_log_t:file { open write getattr };" >> mydaemon.te
重新安装策略:
# ./mydaemon.sh Building and Loading Policy + make -f /usr/share/selinux/devel/Makefile mydaemon.pp Compiling targeted mydaemon module Creating targeted mydaemon.pp policy package rm tmp/mydaemon.mod.fc tmp/mydaemon.mod + /usr/sbin/semodule -i mydaemon.pp ...
验证
检查您的应用程序是否受 SELinux 限制,例如:
$ ps -efZ | grep mydaemon system_u:system_r:mydaemon_t:s0 root 8150 1 0 17:18 ? 00:00:00 /usr/local/bin/mydaemon
验证您的自定义应用程序不会导致任何 SELinux 拒绝:
# ausearch -m AVC -ts recent <no matches>
其他资源
-
sepolgen (8)
,ausearch (8)
,audit2allow (1)
,audit2why (1)
,sealert (8)
, 和restorecon (8)
man page - 快速编写自定义 SELinux 策略 知识库文章