第 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 } ;