Chapter 10. SELinux systemd Access Control In Red Hat Enterprise Linux 7, system services are controlled by the systemd daemon. In releases of Red Hat Enterprise Linux, daemons could be started in two ways: At boot time, the System V init daemon launched an init.rc script and then this script launched the required daemon. For example, the Apache server, which was started at boot, got the following SELinux label: An administrator launched the init.rc script manually, causing the daemon to run. For example, when the service httpd restart command was invoked on the Apache server, the resulting SELinux label looked as follows: When launched manually, the process adopted the user portion of the SELinux label that started it, making the labeling in the two scenarios above inconsistent. With the systemd daemon, the transitions are very different. As systemd handles all the calls to start and stop daemons on the system, using the init_t type, it can override the user part of the label when a daemon is restarted manually. As a result, the labels in both scenarios above are system_u:system_r:httpd_t:s0 as expected and the SELinux policy could be improved to govern which domains are able to control which units. 10.1. SELinux Access Permissions for Services In versions of Red Hat Enterprise Linux, an administrator was able to control, which users or applications were able to start or stop services based on the label of the System V Init script. Now, systemd starts and stops all services, and users and processes communicate with systemd using the systemctl utility. The systemd daemon has the ability to consult the SELinux policy and check the label of the calling process and the label of the unit file that the caller tries to manage, and then ask SELinux whether or not the caller is allowed the access. This approach strengthens access control to critical system capabilities, which include starting and stopping system services. For example, previously, administrators had to allow NetworkManager to execute systemctl to send a D-Bus message to systemd , which would in turn start or stop whatever service NetworkManager requested. In fact, NetworkManager was allowed to do everything systemctl could do. It was also impossible to setup confined administrators so that they could start or stop just particular services. To fix these issues, systemd also works as an SELinux Access Manager. It can retrieve the label of the process running systemctl or the process that sent a D-Bus message to systemd . The daemon then looks up the label of the unit file that the process wanted to configure. Finally, systemd can retrieve information from the kernel if the SELinux policy allows the specific access between the process label and the unit file label. This means a compromised application that needs to interact with systemd for a specific service can now be confined by SELinux. Policy writers can also use these fine-grained controls to confine administrators. Policy changes involve a new class called service , with the following permissions: For example, a policy writer can now allow a domain to get the status of a service or start and stop a service, but not enable or disable a service. Access control operations in SELinux and systemd do not match in all cases. A mapping was defined to line up systemd method calls with SELinux access checks. Table 10.1, "Mapping of systemd unit file method calls on SELinux access checks" maps access checks on unit files while Table 10.2, "Mapping of systemd general system calls on SELinux access checks" covers access checks for the system in general. If no match is found in either table, then the undefined system check is called. Table 10.1. Mapping of systemd unit file method calls on SELinux access checks systemd unit file method SELinux access check DisableUnitFiles disable EnableUnitFiles enable GetUnit status GetUnitByPID status GetUnitFileState status Kill stop KillUnit stop LinkUnitFiles enable ListUnits status LoadUnit status MaskUnitFiles disable PresetUnitFiles enable ReenableUnitFiles enable 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 enable Table 10.2. Mapping of systemd general system calls on SELinux access checks systemd general system call SELinux access check 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 reboot SetUserLinger halt TerminateSeat halt TerminateSession halt TerminateUser halt Example 10.1. SELinux Policy for a System Service By using the sesearch utility, you can list policy rules for a system service. For example, calling the sesearch -A -s NetworkManager_t -c service command returns:

Commands:
system_u:system_r:httpd_t:s0
unconfined_u:system_r:httpd_t:s0
class service { start stop status reload kill load enable disable }
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 } ;