SELinux Policy Overview

This chapter is an overview of SELinux policy, some of its internals, and how it works. It discusses the policy in general terms, while focuses on the details of the targeted policy as it ships in Community Enterprise Linux. This chapter starts with a brief overview of what policy is and where it resides.

Following on from this, the role of SELinux during the boot process is discussed. This is followed by discussions on file security contexts, object classes and permissions, attributes, types, access vectors, macros, users and roles, constraints, and a brief discussion summarizing special kernel interfaces.

What is the SELinux Policy?

The SELinux Policy is the set of rules that guide the SELinux security engine. It defines types for file objects and domains for processes. It uses roles to limit the domains that can be entered, and has user identities to specify the roles that can be attained. In essence, types and domains are equivalent, the difference being that types apply to objects while domains apply to processes.

SELinux Types

A type is a way of grouping items based on their similarity from a security perspective. This is not necessarily related to the unique purpose of an application or the content of a document. For example, a file can have any type of content and be for any purpose, but if it belongs to a user and exists in that user's home directory, it is considered to be of a specific security type, user_home_t.

These object types are considered alike because they are accessible in the same way by the same set of subjects. Similarly, processes tend to be of the same type if they have the same permissions as other subjects. In the targeted policy, programs that run in the unconfined_t domain have an executable file with a type such as sbin_t. From an SELinux perspective, this means they are all equivalent in terms of what they can and cannot do on the system.

For example, the binary executable file object at /usr/bin/postgres has the type postgresql_exec_t. All of the targeted daemons have their own *_exec_t type for their executable applications. In fact, the entire set of PostgreSQL executables such as createlang, pg_dump, and pg_restore have the same type, postgresql_exec_t, and they transition to the same domain, postgresql_t, upon execution.

Using Policy Rules to Define Type Access

The SELinux policy defines various rules which determine how each domain may access each type. Only what is specifically allowed by the rules is permitted. By default, every operation is denied and audited, meaning it is logged in the $AUDIT_LOG file. In Community Enterprise Linux, this is set to /var/log/messages. The policy is compiled into binary format for loading into the kernel security server, and each time the security server makes a decision, it is cached in the AVC to optimize performance.

The policy can be defined either by modifying the existing files or by adding local Type Enforcement (TE) and File Context (FC) files to the policy tree. These new policies can be loaded into the kernel in real time. Otherwise, the policy is loaded during the boot process by init, as explained in . Ultimately, every system operation is determined by the policy and the type-labeling of the files.

After loading a new policy, it is recommended that you restart any services that may have new or changed labeling. Generally speaking, this is only the targeted daemons, as listed in .

SELinux and Mandatory Access Control

SELinux is an implementation of Mandatory Access Control (MAC). Depending on the security policy type, SELinux implements either Type Enforcement (TE), Roles Based Access Control (RBAC) or Bell-La Padula Model Multi-Level Security (MLS).

The policy specifies the rules in the implemented environment. It is written in a language created specifically for writing security policy. Policy writers use m4 macros to capture common sets of low-level rules. A number of m4 macros are defined in the existing policy, which facilitate the writing of new policy. These rules are preprocessed into many additional rules as part of building the policy.conf file, which is compiled into the binary policy.

Access rights are divided differently among domains, and no domain is required to act as a master for all other domains. Moving between domains is controlled by the policy, through login programs, userspace programs such as newrole, or by requiring a new process execution in the new domain. This movement between domains is referred to as a transition.

Where is the Policy?

There are two components to the policy: the binary tree and the source tree. The binary tree is provided by the selinux-policy-<policyname> package and supplies the binary policy file.

Alternatively, the binary policy can be built from source when the selinux-policy-devel package is installed.

Information on how to edit, write and compile policy is currently outside the scope of this document.

Binary Tree Files

Source Tree Files

For developing policy modules, the selinux-policy-devel package includes all of the interface files used to build policy. It is recommended that people who build policy use these files to build the policy modules.

This package installs the policy interface files under /usr/share/selinux/devel/include and has make files installed in /usr/share/selinux/devel/Makefile.

To help applications that need the various SELinux paths, libselinux provides a number of functions that return the paths to the different configuration files and directories. This negates the need for applications to hard-code the paths, especially since the active policy location is dependent on the SELINUXTYPE setting in /etc/selinux/config.

For example, if SELINUXTYPE is set to strict, the active policy location is under /etc/selinux/strict.

To view the list of available functions, use the following command:

man 3 selinux_binary_policy_path

This man page is available only if you have the libselinux-devel RPM installed.

The use of libselinux and related functions is outside the scope of this document.

The Role of Policy in the Boot Process

SELinux plays an important role during the early stages of system start-up. Because all processes must be labeled with their correct domain, init performs some essential operations early in the boot process to maintain synchronization between labeling and policy enforcement.

  1. After the kernel has been loaded during the boot process, the initial process is assigned the predefined initial SELinux ID (initial SID) kernel. Initial SIDs are used for bootstrapping before the policy is loaded.

Object Classes and Permissions

SELinux defines a number of classes for objects, making it easier to group certain permissions by specific classes. For example:

The filesystem class can mount, unmount, get attributes, set quotas, relabel, and so forth. The file class has common file permissions such as read, write, get and set attributes, lock, relabel, link, rename, append, etc.

The object classes have matching declarations in the kernel, meaning that it is not trivial to add or change object class details. The same is true for permissions. Development work is ongoing to make it possible to dynamically register and unregister classes and permissions.

Permissions are the actions that a subject can perform on an object, if the policy allows it. These permissions are the access requests that SELinux actively allows or denies.