SELinux Basics

(Featured image is a well know hex encoding of a code block that is used for buffer overflow attacks)

SELinux Context:

When SELinux is in enabled mode, all the files/processes are labeled with SELinux context. Context made of SELinux user/role/type and possibly a level. SELinux use these data, context, to make access control decisions. RHEL/CentOS provide combination of Role-Based Access Control (RBAC), Type ENforced (TE) and Multi-Level Security (MLS).

You can view a process’s or file/folder’s SELinux context data, user:role:type:level by using -Z with ps or ls. Following example shows context on files inside my home directory.

% ls -Z .
drwxrwxr-x. user user unconfined_u:object_r:user_home_t:s0 tomcat

Lets break down this context so we can understand whats going on.

SELinux Policy:

This is a important piece of understanding what SELinux does and who it does it. Policy is like a umbrella and the connection between users, roles, and domains are known as rules (see below Domain Transition). Policy is a set of rules that are used by SELinux to take action. It defines types for files and domains for processes. It has user identities to define what roles can be taken by the file/process and those roles are used to defined the domain for the process and types for files.

SELinux Type: (TE)

Type is like a label. Anything created by user on user’s home directory will have user_home_t because despite their content or purpose they are all same in the context of security. Which mean if any subject (user/process) want to access those object, they need same privileges. Same goes to the processes, if a process is on a domain, unconfined_t, then

SELinux user (user identities):

SELinux user identity is an identity know to the policy that is authorized for a specific set of roles and for a specific MLS/MCS. This users are mapped to Linux user via a SELinux policy thus inheriting security restrictions from them. These mapped user identity is used in the SELinux context for user’s processes. This inheritance defines the processes domain based on roles associated with that user identity. To check Linux users and SELinux users execute following as root

# semanage login -l
Login Name     SELinux User     MLS/MCS Range      Service

__default__    unconfined_u     s0-s0:c0.c1023     *
root           unconfined_u     s0-s0:c0.c1023     *

Note the __default__, this is what assigned to a user when you create a new user using adduser. It is set to unconfined_u (not so good).

role: (RBAC)

Roles are an intermediary part of domains which the process/file can have. In SELinux users are authorized for roles, and roles are authorized for domains. this connection decouple explicit connection between what a user can do. Nice example would be, GOD mode on a game. In this domain would be everything can be done on a game, the player would the SELinux user and the GOD mode is the role. If you can pay or use a hack to acquire GOD mode, you can do anything like flying or shoot through walls. Essentially roles are something assigned to the user, from which his/her processes able to acquire a domain which its is confined to. Don’t forget the unconfined_t given to unconfined_u.

btw. _t is stand for type, _u stands for user and _r stands for role.


tl:idw; (too long, i didn’t write)

Domain Transition

Problem? You are running HTTPD in your server. You got some PHP scripts that you want to run remotely. In following scenario, I am using hypothetical types but the gist of is same in real life.

How does HTTPD can make PHP execute a php script?

When using SELinux every process has its type. Assume we assign httpd executable httpd_exec_t  and a domain call httpd_t. Then we can create something call a entrypoint that allow files (executabes) with label httpd_exec_t  to run on domain httpd_t . Also for php executable we have a type call php_t. For a process runs on httpd_t domain, we need to define a policy that will allow it to transition its domain so that it can execute files with type php_exec_t. This rule is defined using a SELinux policy. When a user runs the httpd, its process transition in to httpd_t domain. Then we create a policy that says processes runs under httpd_t can access to files with php_t label. Since php executable has the label php_t, httpd can execute it.


Lets look at actual type of httpd file and process. httpd executable file has httpd_exec_t and the process has httpd_t.

[[email protected] ~]# ls -Z /usr/sbin/httpd
-rwxr-xr-x. root root system_u:object_r:httpd_exec_t:s0 /usr/sbin/httpd
[[email protected] ~]# ps -xZ
system_u:system_r:httpd_t:s0     6709 ?        Ss     0:00 /usr/sbin/httpd -DFOREGROUND

Remember that a type defines a type for file and a domain for a process. When I executed #systemclt start httpd, it create a shell that runs httpd, which will transitions to the httpd_t domain. These domain defined by types are further categorized by roles i.e. system_r.


[[email protected] ~]# id -Z

above will tell you your own type. In this case unconfined_t which is mapped to SELinux user unconfined_u.