第 10 章 SELinux systemd 访问控制
在 Red Hat Enterprise Linux 7 中,系统服务由
systemd 守护进程控制。在之前的 Red Hat Enterprise Linux 版本中,可以通过两种方式启动守护进程:
- 引导时,System V
init守护进程启动了init.rc脚本,然后启动该脚本,启动所需的守护进程。例如,在启动时启动的 Apache 服务器具有以下 SELinux 标签:system_u:system_r:httpd_t:s0 - 管理员手动启动
init.rc脚本,从而导致守护进程运行。例如,当 Apache 服务器上调用 service httpd restart 命令时,生成的 SELinux 标签如下:unconfined_u:system_r:httpd_t:s0
手动启动时,进程采用启动它的 SELinux 标签的用户部分,使得以上两个情况下的标记不一致。使用
systemd 守护进程时,转换会有所不同。当 systemd 使用 init_t 类型处理系统上启动和停止守护进程的所有调用时,它可以在守护进程手动重启时覆盖标签的用户部分。因此,上述两个场景中的标签都如预期是 system_u:system_r:httpd_t:s0,SELinux 策略可以改进以管理哪些域能够控制哪些单元。
10.1. 服务的 SELinux 访问权限 复制链接链接已复制到粘贴板!
复制链接链接已复制到粘贴板!
在以前的 Red Hat Enterprise Linux 版本中,管理员可以控制哪些用户或应用程序可以根据 System V Init 脚本标签启动或停止服务。现在,
systemd 会启动并停止所有服务,用户和进程使用 systemctl 工具与 systemd 通信。systemd 守护进程可以参考 SELinux 策略,并检查调用进程的标签以及调用者试图管理的单元文件标签,然后询问 SELinux 是否允许调用者的访问。这个方法可控制对关键系统功能的访问控制,其中包括启动和停止系统服务。
例如,管理员必须允许 NetworkManager 执行
systemctl 向 systemd 发送 D-Bus 消息,这将反过启动或停止任何 NetworkManager 请求的服务。实际上,NetworkManager 允许执行所有 systemctl 可以执行的操作。也无法设置受限管理员,以便他们仅启动或停止特定的服务。
要修复这些问题,
systemd 也作为 SELinux 访问管理器使用。它可以检索运行 systemctl 或向 systemd 发送 D-Bus 消息的进程标签。然后守护进程会查找进程要配置的单元文件标签。最后,如果 SELinux 策略允许进程标签和单元文件标签之间的特定访问,systemd 就可以从内核中检索信息。这意味着,需要与特定服务交互的 systemd 进行交互的应用程序现在可以受 SELinux 限制。策略作者也可以使用这些精细的控制来限制管理员。策略更改涉及一个名为 service 的新类,其具有以下权限:
class service
{
start
stop
status
reload
kill
load
enable
disable
}
例如,策略作者现在可以允许域获取服务状态或启动和停止服务,但不能启用或禁用服务。SELinux 中的访问控制操作和
systemd 在所有情况下都不匹配。定义映射来行使用 SELinux 访问检查的 systemd 方法调用。表 10.1 “在 SELinux 访问检查中映射 systemd 单元文件方法调用” 映射对单元文件的访问检查,表 10.2 “在 SELinux 访问检查中映射 systemd 常规系统调用” 通常涵盖了系统的访问检查。如果在任一表中都未找到匹配项,则将调用 未定义的 系统检查。
systemd 单元文件方法 | SELinux 访问检查 |
|---|---|
| DisableUnitFiles | disable |
| EnableUnitFiles | 启用 |
| GetUnit | status |
| GetUnitByPID | status |
| GetUnitFileState | status |
| kill | stop |
| KillUnit | stop |
| LinkUnitFiles | 启用 |
| ListUnits | status |
| LoadUnit | status |
| MaskUnitFiles | disable |
| PresetUnitFiles | 启用 |
| ReenableUnitFiles | 启用 |
| Reexecute | start |
| reload | reload |
| ReloadOrRestart | start |
| ReloadOrRestartUnit | start |
| ReloadOrTryRestart | start |
| ReloadOrTryRestartUnit | start |
| ReloadUnit | reload |
| ResetFailed | stop |
| ResetFailedUnit | stop |
| Restart | start |
| RestartUnit | start |
| Start | start |
| StartUnit | start |
| StartUnitReplace | start |
| stop | stop |
| StopUnit | stop |
| TryRestart | start |
| TryRestartUnit | start |
| UnmaskUnitFiles | 启用 |
systemd 常规系统调用 | SELinux 访问检查 |
|---|---|
| ClearJobs | reboot |
| FlushDevices | halt |
| Get | status |
| GetAll | status |
| GetJob | status |
| GetSeat | status |
| GetSession | status |
| GetSessionByPID | status |
| GetUser | status |
| halt | halt |
| introspect | status |
| KExec | reboot |
| KillSession | halt |
| KillUser | halt |
| ListJobs | status |
| ListSeats | status |
| ListSessions | status |
| ListUsers | status |
| LockSession | halt |
| PowerOff | halt |
| 重启 | reboot |
| SetUserLinger | halt |
| TerminateSeat | halt |
| TerminateSession | halt |
| TerminateUser | halt |
例 10.1. 系统服务的 SELinux 策略
通过使用
sesearch 工具,您可以列出系统服务的策略规则。例如,调用 sesearch -A -s NetworkManager_t -c service 命令返回:
allow NetworkManager_t dnsmasq_unit_file_t : service { start stop status reload kill load } ;
allow NetworkManager_t nscd_unit_file_t : service { start stop status reload kill load } ;
allow NetworkManager_t ntpd_unit_file_t : service { start stop status reload kill load } ;
allow NetworkManager_t pppd_unit_file_t : service { start stop status reload kill load } ;
allow NetworkManager_t polipo_unit_file_t : service { start stop status reload kill load } ;