![SELinux:获取自定义二进制文件以切换到另一个上下文](https://linux22.com/image/710043/SELinux%EF%BC%9A%E8%8E%B7%E5%8F%96%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6%E4%BB%A5%E5%88%87%E6%8D%A2%E5%88%B0%E5%8F%A6%E4%B8%80%E4%B8%AA%E4%B8%8A%E4%B8%8B%E6%96%87.png)
我正在开发一个必须使用 SELinux 进行保护的新项目。我们有一个用 C 编写的自定义二进制文件(为了回答这个问题,我们将其称为“testprog”),它需要切换到自己的上下文,以便我们可以限制它的操作,而不是让它在不受限制的域中运行。
我根据迄今为止所学的知识创建了一个简单的示例策略文件,但 bash 无法执行该二进制文件。
以下是目前存在的策略文件:
policy_module(testprog, 0.1.6)
require {
type unconfined_t;
class file { ioctl getattr setattr create read write unlink open relabelto };
class process transition;
type fs_t;
class filesystem getattr;
}
type testprog_t;
type testprog_exec_t;
allow testprog_t fs_t:filesystem getattr;
allow testprog_t testprog_exec_t : file { ioctl read getattr lock execute execute_no_trans entrypoint open } ;
type_transition unconfined_t testprog_exec_t : process testprog_t;
allow unconfined_t testprog_t : process transition ;
我已经将二进制文件本身的上下文设置如下:
-rwxr-xr-x. root root system_u:object_r:testprog_exec_t:s0 /usr/bin/testprog
但是,如果我尝试从 bash shell 执行命令,我会收到permission denied
错误,并且在 audit.log 中记录拒绝:
[root@selinux-dev ~]# testprog
type=AVC msg=audit(1504546613.537:237): avc: denied { getattr } for pid=1300 comm="bash" path="/usr/bin/testprog" dev="dm-0" ino=34637336 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:testprog_exec_t:s0 tclass=file
type=SYSCALL msg=audit(1504546613.537:237): arch=c000003e syscall=4 success=no exit=-13 a0=2518ca0 a1=7ffd90223980 a2=7ffd90223980 a3=0 items=0 ppid=1296 pid=1300 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=PROCTITLE msg=audit(1504546613.537:237): proctitle="-bash"
type=AVC msg=audit(1504546613.537:238): avc: denied { getattr } for pid=1300 comm="bash" path="/usr/bin/testprog" dev="dm-0" ino=34637336 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:testprog_exec_t:s0 tclass=file
type=SYSCALL msg=audit(1504546613.537:238): arch=c000003e syscall=4 success=no exit=-13 a0=2518ca0 a1=7ffd90223980 a2=7ffd90223980 a3=0 items=0 ppid=1296 pid=1300 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=PROCTITLE msg=audit(1504546613.537:238): proctitle="-bash"
-bash: testprog: command not found
显然我的政策有点过分。最终,我希望能够从 systemd 运行二进制文件(我的单元文件非常简单,如下所示),但我希望将进程从 bash shell 和 systemd 转换为我创建的 testprog_t 类型。
[Unit]
Description=SELinux Test Program
[Service]
#Type=forking
# The PID file is optional, but recommended in the manpage
# "so that systemd can identify the main process of the daemon"
PIDFile=/var/run/testprog.pid
ExecStart=/usr/bin/testprog /etc/testprog.conf /var/run/testprog.pid
[Install]
WantedBy=multi-user.target
有人能帮我看看我哪里出错了吗?底层操作系统是 RHEL 7.4
谢谢!
答案1
由于参考了大量的参考资料,我最终实现了转换 - 事实上它非常简单,我想您可以说它与良好编程的基本规则有关?
在问题中我发布的政策中,我定义了两种新类型:
type testprog_t;
type testprog_exec_t;
然后继续允许这些类型发生各种事情,并指定类型转换:
allow testprog_t fs_t:filesystem getattr;
allow testprog_t testprog_exec_t : file { ioctl read getattr lock execute execute_no_trans entrypoint open } ;
type_transition unconfined_t testprog_exec_t : process testprog_t;
allow unconfined_t testprog_t : process transition ;
但是,我从来没有真正告诉过 SELinux 这些类型到底是什么。例如,我将文件的上下文设置/usr/bin/testprog
为system_u:object_r:testprog_exec_t:s0
,但我从未通过我的策略真正告诉 SELinux testprog_exec_t 是一个文件。当我通过添加类型规范更改策略时,事情开始变得更加有希望。我还需要使用角色语句来允许在目标 SELinux 模式下在 RHEL 系统上 shell 命令通常运行的角色testprog_t
下运行unconfined_r
。与此相关的策略的当前片段如下所示:
# Define our new types that testprog will use, and ensure that we tell the policy that testprog_exec_t is a file
type testprog_t;
domain_type(testprog_t);
type testprog_exec_t;
files_type(testprog_exec_t);
type testprog_etc_t;
files_type(testprog_etc_t);
type testprog_var_run_t;
files_type(testprog_var_run_t);
type testprog_data_t;
files_type(testprog_data_t);
# Allow the testprog_t type under the unconfined_r role
role unconfined_r types testprog_t;
# Tell SELinux that testprog_exec_t is an entrypoint to the tetprog_t domain
allow testprog_t testprog_exec_t : file { ioctl read getattr lock execute execute_no_trans entrypoint open } ;
# Make the type transition from unconfined_t (i.e. user shell) to testprog_t
type_transition unconfined_t testprog_exec_t : process testprog_t;
# Explicitly allow the type transition we have just created
allow unconfined_t testprog_t : process transition ;
完成此操作后,类型转换就完美地发生了,完成策略的工作就变成了sealert
探索程序的行为并制定正确的策略以使其按预期工作。
我希望整理一个完整的工作示例,该示例是一个非 SELinux 感知应用程序,需要在它自己的受限上下文中运行,而不是为我的同事(以及任何需要它的人)不受限制地运行 - 现在它还很粗略,但如果有人有兴趣跟踪它,你可以在这里找到代码: