New Red Hat Enterprise Linux 7 Security Feature: systemd Starting Daemons
Why is this a security feature?
In previous releases of Red Hat Enterprise Linux, system daemons would be started in one of two ways:
- At boot,
init
(sysV
) launches aninitrc
script and then this script launches the daemon. - An admin can log in and launch the
init
script by hand, causing the daemon to run.
Let me show you what this means from an SELinux point of view.
NOTE: In the code below, @
means execute, -->
indicates transition, and ===
indicates a client/server communication.
The init
process executes an Apache init
script, which in turn executes the Apache executable.
~~
init_t @ initrc_exec_t --> initrc_t @ httpd_exec_t --> httpd_t:
~~
This Apache processes would end up running with the full label of:
system_u:system_r:httpd_t:s0
If Apache created content, it would probably be labeled
system_u:object_r:httpd_sys_content_rw_t:s0
When an administrator, probably running as unconfined_t
, started or restarted a service using service httpd restart
:
unconfined_t @initrc_exec_t --> initrc_t @httpd_exec_t --> httpd_t
Notice the process would adopt the user portion of the SELinux label that started it.
unconfined_u:system_r:httpd_t:s0
Content created by this Apache process would be:
unconfined_u:object_r:httpd_sys_content_rw_t:s0
SELinux ends up confusing the user. In SELinux targeted and MLS policy, we ignore the user component of the SELinux label. Even if you wanted to write policy to confine based on user type, you can't.
However, systemd fixes this problem. The transitions is very different:
init_t @ httpd_exec_t --> httpd_t
system_u:system_r:httpd_t:s0
If you want to restart the Apache daemon as admin, do so now.
unconfined_t === init_t @ httpd_exec_t --> httpd_t
system_u:system_r:httpd_t:s0
With systemd
, we don't have the labeling problem and we can tighten up the SELinux policy.
Systemd Starting Daemons Affects More Than SELinux
Admins restarting daemons results in having to work around a lot of vulnerabilities and administration failures. Daemons need to be coded to clean up any leaked information from the admin process influencing the way the daemon ran
- Need to clean $ENV
- Need to change working directory in order to make sure they don't blow up because they lack access to the current working directory (if you look at the
/sbin/service
script, you will see that one of the first things it does iscd /
. - Need do something with the terminal (close
stdin
,stdout
,stderr
after they start) - Any open File descriptor in the user session also needs to be closed to make sure a daemon does not potentially gain access to tcp sockets or important content that the user had access to (in SELinux, we are always in a quandary about this because if we allow the daemon access to the terminal, a hacked daemon could present the admin with
passwd
and trick him into revealing the admin password) - Change the controlling terminal
- Change the handling of signals
- ...
If a daemon writer screws up on one of these, he could make the system vulnerable or end up with unexpected bugs.
Using systemd
to start daemons guarantees the daemon always gets started with the same environment, whether they are started at boot or restarted by an administrator.
Comments