The Art of Guard, Part 2: SELinux Modes and Policies


In Part 1 of this series, we discussed the basics of host security through traditional security mechanisms (DAC) and newer efficient mechanisms (MAC). We also understood that the right combination of both the Access Control Methods eventually leads to an effective security policy that can be applied to any host.

We learnt that applying security to an operating system as a whole was far more practical and efficient than applying security to each individual application running on the operating system, and that SELinux was one such mechanism. SELinux achieves MAC objectives by applying a ‘Security Context’ to subjects and objects, and by controlling access of subjects to objects based on access control rules.

In Part I, we also learnt to enable SELinux on Red Hat Enterprise Linux. The steps are briefly summarised below:

  1. Edit /etc/sysconfig/selinux and make sure it contains the lines:
  2. Reboot and check.

In this article, we will explore Permissive and Reboot and check. Enforcing Modes. We will also learn a few SELinux commands that will help in understanding SELinux policies better.

Understanding SELinux modes

Irrespective of the policy or the rules implemented through SELinux Type Enforcement, there are three modes of operation for SELinux:

  1. Disabled
  2. Permissive
  3. Enforcing

Disabled mode implies that SELinux is disabled and not implemented on the host. This has been the most common choice in installations seen by me. Hopefully, by the end of this series, we shall be able to bring about a change in that practice by encouraging more system administrators to adopt SELinux.

Permissive mode is similar to Debugging Mode. In Permissive Mode, SELinux policies and rules are applied to subjects and objects, but actions (for example, Access Control denials) are not effected. The biggest advantage of Permissive Mode is that log files and error messages are generated based on the SELinux policy implemented.

In other words, if the SELinux policy would prevent the httpd subject (Apache Web server) from accessing the object folder /webdata on my system, implementing SELinux in Permissive Mode would let the Apache Web server access the folder /webdata but log a denial in the log files.

This error logging informs the system administrator that if SELinux is activated in the Enforcing Mode, the httpd subject would be disallowed access to the /webdata folder on my system.

Permissive Mode is the initiating point for all those wanting to explore the world of Type Enforcement through SELinux. Without blocking access to your favourite programs such as, Evolution, etc, it provides you with enough debugging information to fine tune your policy before deploying it on your system.

Enforcing Mode, as the name signifies, is SELinux in action. All production systems, when hardened, should enable SELinux in Enforcing Mode. SELinux through Access Controls does have a minor performance overhead, but compared to the advantages that it brings to the table, I am sure it will soon become the norm to implement SELinux on production servers.

Controlling SELinux

The getenforce command gets the current mode of SELinux. It reports whether SELinux is Enforcing, Permissive, or Disabled.On a system with SELinux disabled, it will display the following:

[root@station20 ~]# getenforce

On a system with SELinux in Permissive Mode, it will display:

[root@vbg ~]# getenforce

On a system with SELinux in Enforcing Mode, the following will be displayed:

[root@vbg ~]# getenforce

setenforce modifies the mode SELinux is running in. It is used to toggle between Permissive and Enforcing mode when SELinux is enabled.

To activate “Enforcing mode” on an SELinux-enabled system, run:

[root@vbg ~]# setenforce 1

To check the current status, use getenforce. To activate Permissive SELinux mode, execute:

[root@vbg ~]# setenforce 0

The sestatus command is used to get the status of a system running SELinux. Apart from mentioning the current mode of SELinux, it gives more information about the SELinux policy.

On a system with SElinux disabled, it will display:

[root@station20 ~]# sestatus
SELinux status:                 disabled

On a System with SELinux in Permissive Mode, it will display:

[root@vbg ~]# sestatus
SELinux status:                 enabled
SELinuxfs mount:              /selinux
Current mode:                   permissive
Mode from config file:         permissive
Policy version:                   21
Policy from config file:        targeted

The first line informs us that SELinux is enabled in this system.

The second line is of great significance. It displays the mount point of the SELinux pseudo file system. This file system is quite like the proc and sys file systems, and contains run-time information about your SELinux mode and various other things.

You can change run-time parameters of the SELinux system by directly writing to the files in this pseudo file system. As an example, just issue this command as the root user:

[root@vbg ~]# echo 1 > /selinux/enforce

You will see that the mode of SELinux has changed from Permissive to Enforcing.

To return back to Permissive Mode, you can run either of the commands:

[root@vbg ~]# echo 0 > /selinux/enforce


[root@vbg ~]# setenforce 0

The third line mentions the current SELinux mode, whereas the fourth line mentions the SELinux mode under which the system booted.

The fifth line mentions the version number of the policy (we will come to this later in this series) and finally, the sixth line mentions the Policy loaded from the configuration file (/etc/sysconfig/selinux) at boot time.

Understanding various types of policies

By definition, an SELinux policy is a collection of rules for SELinux Mandatory Access Controls. Each one of us can make a policy to suit our needs much like we define firewall rules through iptables. There can be no standard policy that can apply to all situations.

By default, there are two policies shipped along with Red Hat Enterprise Linux: Targeted and Strict.

The Targeted Policy is the first step in assisting system administrators to understand and implement SELinux. It only ‘targets’ certain network daemons such as the Apache Web server, FTP server, BIND DNS server and a few others, while leaving the vast majority of end-user applications largely untouched. It creates an ‘unconfined’ domain ‘confinement’ (interesting paradox, isn’t it?) and does not apply Access Control Restrictions to most applications in the unconfined domain.

This allows sysadmins to concentrate on the really vulnerable network applications and services while not interfering with their daily tasks.

Once the nuts and bolts of SELinux are clear to administrators, they should move forward towards implementing the SELinux Strict Policy.

The Strict Policy, on the other hand, is a true restrictive Access Control Policy. Before implementing this policy, make sure you understand SELinux concepts and policies well.

Under the hood of Targeted Policy

To understand any SELinux policy, use the informative command—seinfo.

[root@vbg ~]# seinfo
Statistics for policy file: /etc/selinux/targeted/policy/policy.21
Policy Version & Type: v.21 (binary, MLS)

Classes:            61    Permissions:       220
Types:            1513    Attributes:        148
Users:               3    Roles:               6
Booleans:          210    Cond. Expr.:       186
Sensitivities:       1    Categories:       1024
Allow:           82518    Neverallow:          0
Auditallow:         28    Dontaudit:        5086
Role allow:          5    Role trans:          0
Type_trans:       1398    Type_change:        17
Type_member:         0    Range_trans:        23
Constraints:        47    Validatetrans:       0
Fs_use:             15    Genfscon:           64
Portcon:           264    Netifcon:            0
Nodecon:             8    Initial SIDs:       27

seinfo is a policy query tool that queries policy files and provides vital information about it. When executed without any arguments, it queries the default loaded policy file.

As you can see the policy file read by the seinfo tool by default is /etc/selinux/targeted/policy/policy.21. Installed by the selinux-policy-targeted RPM, this file contains the binary Targeted Policy.

The second line of the above output mentions that this is a binary policy with MLS (Multi Level Security). We will come to MLS in the later part of this series.

Now comes the interesting part of the output. You can clearly see various components of the policy. We will discuss these components in the course of these articles. Let us concentrate on a few important ones right now.

A typical security context as we discussed in Part 1 of this series, is of the type:

User Identity:Role:Type/Domain

As we can see from the above, in the default SELinux Targeted policy, there are:

  1. Users (3 in number)
  2. Roles (6 in number)
  3. Types (1,513 in number)

This means that any object or subject in the SELinux Policy installed in the system can have one of three user identities, one of six roles and one of the available 1,513 types.

To list user identities defined in the SELinux Targeted Policy, run the following command:

[root@vbg ~]# seinfo -u

Users: 3

Do check all possible security contexts for objects (files, dirs, etc) and subjects (processes) in your system. The user identitity component of the Security context will have one of the above three identities and nothing else.

Similarly, to check the available roles, use the following code:

[root@vbg ~]# seinfo -r

Roles: 6

And please check the available list of types yourself by using the command given below:

[root@vbg ~]# seinfo -t

Thus we now know that any existing object or subject in the system will have a security context created out of these three users, six roles and 1,513 types.

You can alter the security context of any object by using the chcon command.

To change the type of an object, use chcon -t. To change the user identity, use chcon -u and chcon -r for role.

To test the above, create an empty file “context” in the /tmp directory and check its default security context:

[root@vbg ~]# touch /tmp/context
[root@vbg ~]# ls -lZ /tmp/context
-rw-r--r--  root root user_u:object_r:tmp_t:s0         /tmp/context

To change the type of this object from tmp_t to unconfined_t, use the code below:

[root@vbg ~]# chcon -t unconfined_t /tmp/context
[root@vbg ~]# ls -Z /tmp/context
-rw-r--r--  root root root:object_r:unconfined_t:s0    /tmp/context

I leave it as an exercise for you to change the role and the user for this object. If you face any issues, feel free to contact me at the e-mail ID provided below.

Assuming that, as above, you have changed the security context of an object quite a few times and you would like to revert back to the original/default security context, restorecon comes to the rescue.

restorecon restores files to their default security contexts. The verbose option of the restorecon command also displays the changes made in the security context. To check the usage of this very handy command, look at the example below:

[root@vbg ~]# touch /home/vbg/test-context
[root@vbg ~]# ls -Z /home/vbg/test-context
-rw-rw-r--  vbg vbg
user_u:object_r:user_home_t:s0         /home/vbg/test-context

[root@vbg ~]# chcon -t tmp_t /home/vbg/test-context

[root@vbg ~]# ls -Z /home/vbg/test-context
-rw-rw-r--  vbg vbg user_u:object_r:tmp_t:s0         /home/vbg/test-context

[root@vbg ~]# restorecon -v /home/vbg/test-context
restorecon reset /home/vbg/test-context context user_u:object_r:tmp_t:s0->user_u:object_r:user_home_t:s0

[root@vbg ~]# ls -Z /home/vbg/test-context
-rw-rw-r--  vbg vbg user_u:object_r:user_home_t:s0   /home/vbg/test-context

The above snippet shows the utility of the restorecon command. It reads the default contexts to be applied from the policy files and applies the default security context to a file/directory object.

A word of caution when using restorecon: DO NOT use the command with the -r (recursive) option. It may overwrite the security contexts of some important files in the system that you may have changed.

If you think that you have spoilt the security contexts of the files in your system beyond recovery, do not panic. Help is available in the form of Auto-Relabel, at boot. Simply create an empty file /.autorelabel. Please note that it is a hidden file.

[root@vbg ~]# touch /.autorelabel
[root@vbg ~]# reboot

Following the procedure mentioned above will cause SELinux to relabel the files on your system upon rebooting. Please use this to fix any improper security context on files and directories.

You can also use the fixfiles command to achieve the above. fixfiles can prevent you from rebooting your system but may not be as effective. Depending on the options and time available, you can choose any option that suits you—though I would suggest the reboot option.

Still to come

So, that’s about it for now. I’ll be back the following months with topics such as:

  • Understanding the Targeted Policy – Part II
  • Policy Modules
  • MLS and MCS


  1. hello
    this is great tutorial about se_linux
    but i want to know where can i found the part one for this tutorial
    many thanks for you
    wait your response

  2. hello
    this is great tutorial about se_linux
    but i want to know where can i found the part one for this tutorial
    many thanks for you
    wait your response

  3. hello
    this is great tutorial about se_linux
    but i want to know where can i found the part one for this tutorial
    many thanks for you
    wait your response

  4. good article. I wish I could read all parts of your series (I found 2 and 5), what about 1,3,4 and any others.

    How do I setup the domain of a service started by init.d? A process of this service needs access to all of /proc, but with the inherited domain init_t, it cannot access aall it needs to.


Please enter your comment!
Please enter your name here