Log in

No account? Create an account

Previous Entry Share Next Entry
New Security Feature in Fedora 18 Part 1: SELinux Systemd Access Control

For Fedora 17 I did a series of blogs on new security features. I guess it is time to start it for Fedora 18.
If you want me to talk about a new security feature,  email dwalsh@redhat.com, or comment on this blog.

New Feature in Fedora 18 SELinux Systemd Access Control.

In previous versions of Fedora/RHEL SELinux could control which processes were able to start/stop services based on the label of the process and the label on the Init Script.

For example NetworkManager (NetworkManager_t) was allowed to execute /etc/init.d/ntp (ntp_initrc_exec_t) but not allowed to access /etc/init.d/httpd (httpd_initrc_exec_t).

With the advent of systemd we lost this ability since systemd starts and stops all services.

We had to allow NetworkManager (NetworkManager_t) to execute systemctl which would send a dbus message to systemd, and systemd would start/stop whatever service NetworkManager requested. Actually we ended up allowing NetworkManager to do everything systemctl could do.   We also wanted to setup confined administrators, but we ended up having to allow them to either start/stop all services or no services.  We could no longer allow the webadm_t to only start/stop httpd_t.

In Fedora 18, we have fixed this by making systemd an SELinux Access Manager.  Now systemd will retrieve the label of the process running systemctl or the process that sent systemd a dbus message.  systemd will then look up the label of the unit file that the process wanted to configure.  Finally systemd will ask the kernel if SELinux policy allows the specific access between the process label and the unit file label.  This means a hacked NetworkManager or any other application that needs to interact with systemd for a specific service can now be confined via SELinux.  Policy writers can use these fined grained controls to confine administrators.

Policy changes.

We have added a new class to SELinux Policy called "service".  The service class has the following permissions defined:

start stop status reload kill load enable disable

This means a policy writer can allow a domain to get the status on a service or start and stop a service, but not enable or disable a service.  This gives us better control then we have ever had in the past.

To demonstrate this, I setup webadm_t as my root process:
Note: For more information on setting up confined users see my other blogs.

# id -Z
# /bin/systemctl status httpd.service
httpd.service - The Apache HTTP Server
      Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
      Active: inactive (dead)
      CGroup: name=systemd:/system/httpd.service

# /bin/systemctl status NetworkManager.service
Failed to issue method call: SELinux policy denies access.

In a separate window running as unconfined_t, I can look at the AVC message created.

# id -Z
# ausearch -m user_avc
time->Thu Sep 27 08:54:10 2012
type=USER_AVC msg=audit(1348750450.105:135): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='avc:  denied  { status } for auid=3267 uid=0 gid=0 path="/usr/lib/systemd/system/NetworkManager.service" cmdline="/bin/systemctl status NetworkManager.service" scontext=staff_u:webadm_r:webadm_t:s0-s0:c0.c1023 tcontext=system_u:object_r:NetworkManager_unit_file_t:s0 tclass=service  exe="/usr/lib/systemd/systemd" sauid=0 hostname=? addr=? terminal=?'

And of course you could use audit2allow to write policy to allow this access.

audit2allow -la
#============= webadm_t ==============
allow webadm_t NetworkManager_unit_file_t:service status;

# audit2allow -laR
#============= webadm_t ==============

Make sure you have the latest systemd and selinux-policy to try this out.  These are my current versions:

rpm -q selinux-policy systemd

  • 1

if NetworkManager can be hacked, so can systemd

It seems to me that for this to be effective the control has to happen at a lower level. Systemd asking the kernel is a security risk.

Is this feasible ?, could Systemd be forced to take the selinux identity of the caller ? (this way, each Systemd service can be relabeled with the correct label)


  • 1