Book Image

SELinux System Administration

By : Sven Vermeulen
Book Image

SELinux System Administration

By: Sven Vermeulen

Overview of this book

NSA Security-Enhanced Linux (SELinux) is a set of patches and added utilities to the Linux kernel to incorporate a strong, flexible, mandatory access control architecture into the major subsystems of the kernel. With its fine-grained yet flexible approach, it is no wonder Linux distributions are firing up SELinux as a default security measure. SELinux System Administration covers the majority of SELinux features through a mix of real-life scenarios, descriptions, and examples. Everything an administrator needs to further tune SELinux to suit their needs are present in this book. This book touches on various SELinux topics, guiding you through the configuration of SELinux contexts, definitions, and the assignment of SELinux roles, and finishes up with policy enhancements. All of SELinux's configuration handles, be they conditional policies, constraints, policy types, or audit capabilities, are covered in this book with genuine examples that administrators might come across. By the end, SELinux System Administration will have taught you how to configure your Linux system to be more secure, powered by a formidable mandatory access control.
Table of Contents (13 chapters)

Policies – the ultimate dictators


Enabling SELinux does not automatically start enforcement of access, if SELinux is enabled and it cannot find a policy, it will refuse to start. That is because the policy defines the behavior of the system (what should SELinux allow). Because SELinux is extremely flexible, its policy developers already started differentiating one policy implementation from another through what it calls a policy type or policy store.

A policy store contains a single policy, and only a single policy can be active on a system at any point in time. Administrators can switch a policy, although this requires the system to be rebooted, and might even require relabeling the entire system (relabeling is the act of resetting the contexts on all files and resources available on that system). The active policy on the system can be queried using sestatus (SELinux status) as follows:

# sestatus | grep "Loaded policy"
Loaded policy name:             targeted

In the preceding example, the currently loaded policy is named targeted. The policy name that SELinux will use upon its next reboot is defined in the /etc/selinux/config configuration file as the SELINUXTYPE parameter.

Most SELinux supporting distributions base their policy on the reference policy [http://oss.tresys.com/projects/refpolicy/], a fully functional SELinux policy set managed as a free software project. This allows distributions to ship with a functional policy set rather than having to write one themselves. Many project contributors are distribution developers, trying to push changes of their distribution to the reference policy project itself, where the changes are peer-reviewed to make sure no rules are brought into the project that might jeopardize the security of any platform.

SELinux policy store names and options

The most common SELinux policy store names are strict, targeted, mcs, and mls. None of the names assigned to policy stores are fixed though, so it is a matter of convention. Hence, it is recommended to consult the distribution documentation to verify what should be the proper name of the policy. Still, the name often gives some information about the options that are enabled on the system.

MLS status

One of the options is MLS support that can either be enabled or disabled. If disabled, then the SELinux context will not have a fourth field with sensitivity information in it, making the contexts of processes and files look as follows:

staff_u:sysadm_r:sysadm_t

To check if MLS is enabled, it is sufficient to see if the context indeed doesn't contains such a fourth field, but it can also be acquired from the Policy MLS status line in the output of sestatus:

# sestatus | grep MLS
Policy MLS Status:            disabled

Another method would be to look into the pseudo file, /sys/fs/selinux/mls. a value of 0 means disabled, whereas a value of 1 means enabled:

# cat /sys/fs/selinux/mls
0

Dealing with unknown permissions

Permissions (such as read, open, and lock) are defined both in the Linux kernel and in the policy itself. However, sometimes newer Linux kernels support permissions that the current policy doesn't.

A recently introduced one is block_suspend (to be able to block system suspension) and when that occurs, SELinux has to take the decision: as the policies are not aware of this new permission, how should it deal with the permission when triggered? SELinux can allow (assume everything is allowed to perform this action), deny (assume no one is allowed to perform this action), or reject (stop loading the policy at all and halt the system) the request. This is configured through the deny_unknown value.

To see the state for unknown permissions, look for the Policy deny_unknown status line in sestatus:

# sestatus | grep deny_unknown
Policy deny_unknown status:   denied

Administrators can set this for themselves in the /etc/selinux/semanage.conf file through the handle-unknown key (with allow, deny, or reject).

Supporting unconfined domains

A SELinux policy can be written as very strict, limiting applications as close as possible to their actual behavior, but it can also be written to be very liberal in what applications are allowed to do. One of the concepts available in many SELinux policies is the idea of unconfined domains. When enabled, it means that certain SELinux domains (process contexts) are allowed to do almost anything they want (of course within the boundaries of the regular Linux DAC permissions which still hold) and only a few selected are truly confined (restricted) in their actions.

Unconfined domains have been brought forward to allow SELinux to be active on desktops and servers where administrators do not want to fully restrict the entire system, but only a few of the applications running on it.

With other MAC systems, for example, AppArmor, this is inherently part of the design of the system. However, SELinux was designed to be a full mandatory access control system and thus needs to provide access control rules even for those applications that shouldn't need any. By marking these applications as unconfined, almost no additional restrictions are imposed by SELinux.

We can see if unconfined domains are enabled on the system through seinfo:

# seinfo -tunconfined_t
  unconfined_t
# seinfo -tunconfined_t
ERROR: could not find datum for type unconfined_t

Most distributions that enable unconfined domains call their policy targeted, but this is just a convention that is not always followed. Hence, it is always best to consult the policy using seinfo to make this sure.

User-based access control

When UBAC is enabled, certain SELinux types will be protected by additional constraints. This will ensure that one SELinux user cannot access files (or other specific resources) of another user. UBAC gives some additional control on information flow between resources, but is far from perfect. In its essence, it is made to isolate SELinux users from one another.

Many Linux distributions disable UBAC. Gentoo allows users to select if they want UBAC or not through a Gentoo USE flag (which is enabled by default).

Policies across distributions

As mentioned, policy store names are not standardized. What is called targeted in Fedora is not targeted in Gentoo. Of the options mentioned previously, the following table shows us how some of the policy stores are implemented across these two distributions:

Distribution

Policy store name

MLS?

deny_unknown

Unconfined domains?

UBAC?

Gentoo

strict

No

denied

No

Yes (configurable)

Fedora 19

minimum

Yes (only s0)

allowed

Yes, but limited

No

Gentoo

targeted

No

denied

Yes

Yes (configurable)

Fedora 19

targeted

Yes (only s0)

allowed

Yes

No

Gentoo

mcs

Yes (only s0)

denied

Yes (configurable)

Yes (configurable)

Gentoo

mls

Yes

denied

Yes (configurable)

Yes (configurable)

Fedora 19

mls

Yes

allowed

Yes

No

Other distributions might even have different names and implementation details.

Yet, besides the naming differences, many of the underlying settings can be changed by the administrator. For instance, even though Fedora does not have a strict policy, it does have a documented approach on running Fedora without unconfined domains. It would be wrong to state that Fedora as such does not support fully confined systems.

MCS versus MLS

In the feature table, we notice that for MLS, some policies only support a single sensitivity (s0). When this is the case, we call the policy an MCS (Multi Category Security) policy. The MCS policy enables sensitivity labels, but only with a single sensitivity while providing support for multiple categories (and hence the name).

With the continuous improvement made in supporting Linux in PaaS (Platform as a Service) environments, implementing proper multitenancy requires proper security isolation as a vital part of its offering.

Policy binaries

While checking the output of sestatus, we see that there is also a notation of policy versions:

# sestatus | grep version
Max kernel policy version:      28

As the output states, 28 is the highest policy version the kernel supports. The policy version refers to the supported features inside the SELinux policy: every time a new feature is added to SELinux, the version number is increased. The policy file itself (which contains all the SELinux rules loaded at boot time by the system) can be found in /etc/selinux/targeted/policy (where targeted refers to the policy store used, so if the system uses a policy store named strict, then the path would be /etc/selinux/strict/policy).

If multiple policy files exist, we can use the output of seinfo to find out which policy file is used:

# seinfo
Statistics for policy file: /etc/selinux/targeted/policy/policy.27
Policy Version & Type: v.27 (binary, mls)
...

The next table gives the current list of policy feature enhancements and the Linux kernel version in which that feature is introduced. Many of the features are only of concern to the policy developers, but knowing the evolution of the features gives us a good idea on the evolution of SELinux.

Version

Linux kernel

Description

12

 

It is the "Old API" for SELinux, now deprecated

15

2.6.0

It is the "New API" for SELinux

16

2.6.5

It provides conditional policy extensions

17

2.6.6

It provides IPv6 support

18

2.6.8

It adds fine-grained netlink socket support

19

2.6.12

It provides enhanced multi-level security

20

2.6.14

It doesn't access vector table size optimizations”, the version (20) improved the access vector table size (it is a performance optimization).

21

2.6.19

It provides object classes in range transitions

22

2.6.25

It provides policy capabilities (features)

23

2.6.26

It provides per-domain permissive mode

24

2.6.28

It provides explicit hierarchy (type bounds)

25

2.6.39

It provides filename based transition support

26

3.0

It provides role transition support for non-process classes

27

3.5

It supports flexible inheritance of user and role for newly created objects

28

3.5

It supports flexible inheritance of type for newly created objects

By default, when a SELinux policy is built, the highest supported version as defined by the Linux kernel and libsepol (the library responsible for building the SELinux policy binary) is used. Administrators can force a version to be lower using the policy-version parameter in /etc/selinux/semanage.conf.

SELinux policy modules

Initially, SELinux used a single, monolithic policy approach: all possible access control rules are maintained in a single, binary policy file that the SELinux utilities then load. It quickly became clear that this is not manageable in long term, and thus the idea of developing a modular policy approach was born.

Within the modular approach, policy developers can write isolated policy sets for a particular application (or set of applications), roles, and so on. These policies then get built and distributed in their own policy modules. Platforms that need access controls for that particular application load the SELinux policy module that defines the access rules.

On some Linux distributions, these SELinux policy modules are stored inside /usr/share/selinux, usually within a subdirectory named after the policy store (such as "targeted" or "strict"). The policy modules that are currently loaded are always available in /etc/selinux/targeted/modules/active and its modules subdirectory.

Of all the *.pp files in these locations, the base.pp one is special. This policy module file contains core policy definitions. The remaining policy module files are "isolated" policy modules, providing the necessary rules for the system to handle applications and roles related to the module itself. For instance, the screen.pp module contains the SELinux policy rules for the GNU screen (and also tmux) application.

Once those files are placed on the system, the distribution package manager usually calls the semodule command to load the policy modules. This command then combines the files into a single policy file (for example, policy.28) and loads it in memory.

On Fedora, the SELinux policies are provided by the selinux-policy-targeted (or -minimum or -mls) package. On Gentoo, they are provided by the various sec-policy/selinux-* packages (Gentoo uses separate packages for each module, reducing the amount of SELinux policies that are loaded on an average system).