Magazine

Labeling All Resources and Objects

Posted on the 23 May 2021 by Satish Kumar @satish_kumar86

When SELinuxhas to decide whether it has to allow or deny a particular action, it makes a decision based on the context of both thesubject(who is initiating the action) and theobject(which is the target of the action). These contexts (or parts of the context) are mentioned in the policy rules that SELinux enforces.

Thecontextof a process is what identifies the process to SELinux. SELinux has no notion of Linux process ownership and does not care how the process is called, which process ID it has, and what account the process runs as. All it wants to know is what the context of that process is, represented to users and administrators as alabel.Labelandcontextare often used interchangeably, and although there is a technical distinction (one is a representation of the other), we will not dwell on that much.

Let’s look at an example label – the context of the current user:

$ id -Z 
sysadm_u:sysadm_r:sysadm_t:s0-s0:c0.c1023

Theidcommand, which returns information about the current user, is shown executing with the-Zswitch (a commonly agreed upon switch for displaying additional security information obtained from the LSM-based security subsystem). It shows us the context of the current user (actually the context of theidprocess itself when it was executing). As we can see, the context has a string representation and looks as if it has five fields (it doesn’t; it has four fields – the last field just happens to contain a colon character).

SELinux developers decided to use labels instead of real process and file (or other resource) metadata for its access controls. This is different from MAC systems such as AppArmor, which uses the path of the binary (and thus the process name) and the paths of the resources to handle permission checks. The following reasons inspired the decision to make SELinux a label-based mandatory access control:

  • Using paths might be easier to comprehend for administrators, but this doesn’t allow us to keep the context information close to the resource. If a file or directory moves or remounts, or if a process has a different namespace view on the files, then the access controls might behave differently as they look at the path instead of the file. With label-based contexts, the system retains this information and keeps controlling the resource’s access properly.
  • Contexts reveal the purpose of the process very well. The same binary application can be launched in different contexts depending on how it got started. The context value (such as the one shown in theid -Zoutput earlier) is exactly what the administrator needs. With it, they know what the rights are of each of the running instances, but they can also deduce from it how the process was launched and what its purpose is.
  • Contexts also make abstractions of the object itself. We are used to talking about processes and files, but contexts are also applicable to less tangible resources such as pipes (inter-process communication) or database objects. Path-based identification only works as long as you can write a path.

As an example, consider the following policy statements:

  • Allow thehttpdprocesses to bind to TCP port80.
  • Allow the processes labeled withhttpd_tto bind to TCP ports labeled withhttp_port_t.

In the first example, we cannot easily reuse this policy when the web server process isn’t using the httpd binary (perhaps because it was renamed or it isn’t Apache but another web server) or when we want to have HTTP access on a different port. With the labeled approach, the binary could be called apache2 or MyWebServer.py; as long as the process is labeled with httpd_t, the policy applies. The same happens with the port definition: you can label the port 8080 with http_port_t and thus allow the web servers to bind to that port as well without having to write another policy statement.

Dissecting the SELinux context

To come to a context, SELinux uses at least three, and sometimes four, values. Let’s look at the context of the SSH server as an example:

$ ps -eZ | grep sshd
system_u:system_r:sshd_t:s0-s0:c0.c1023 2629 ? 00:00:00 sshd

As we can see, the process is assigned a context that contains the following fields:

  • The SELinux usersystem_u
  • The SELinux rolesystem_r
  • The SELinux type (also known as the domain when we are looking at a running process)sshd_t
  • The sensitivity levels0-s0:c0.c1023

When we work with SELinux, knowing the contexts is extremely important. In most cases, it is thethird field (called thedomainortype) thatis most important since the majority of SELinux policy rules (over 99 percent) consist of rules related to the interaction between two types (without mentioning roles, users, or sensitivity levels).

SELinux contexts are aligned with LSM security attributes and exposed to the user space in a standardized manner (compatible with multiple LSM implementations), allowing end users and applications to easily query the contexts. An easily accessible location where these attributes are presented is within the/procpseudo filesystem.

Inside each process’s/proc/<pid>location, we find a subdirectory calledattr, inside of which the following files can be found:

$ ls /proc/$$/attr
current  exec  fscreate  keycreate  prev  sockcreate

All these files, if read, display either nothing or an SELinux context. If it is empty, then that means the application has not explicitly set a context for that particular purpose, and the SELinux context will be deduced either from the policy or inherited from its parent.

The meaningof the files are as follows:

  • Thecurrentfile displays the current SELinux context of the process.
  • Theexecfile displays the SELinux context that will be assigned by the next application execution done through this application. It is usually empty.
  • Thefscreatefile displays the SELinux context that will be assigned to the next file written by the application. It is usually empty.
  • Thekeycreatefile displays the SELinux context that will be assigned to the keys cached in the kernel by this application. It is usually empty.
  • Theprevfile displays the previous SELinux context for this particular process. This is usually the context of its parent application.
  • Thesockcreatefile displays the SELinux context that will be assigned to the next socket created by the application. It is usually empty.

If an application has multiple subtasks, then the same information is available in each subtask directory at /proc/<pid>/task/<taskid>/attr

Enforcing access through types

The SELinux type (the third part of an SELinux context) ofa process (called thedomain) is the basis of the fine-grained access controls of that process with respect to itself andother types (which can be processes, files, sockets, network interfaces, and more). In most SELinux literature, SELinux’s label-based access control mechanism is fine-tuned to say that SELinux is atype enforcementmandatoryaccess control system: when some actions are denied, the (absence of the) fine-grained access controls on the type level are most likely to blame.

With type enforcement, SELinux can control an application’s behavior based on how it got executed in the first place: a web server launched by a user will run with a different type than a web server executed through theinitsystem, even though the process binary and path are the same. The web server launched from theinitsystem is most likely trusted (and thus allowed to do whatever web servers are supposed to do), whereas a manually launched web server is less likely to be considerednormal behaviorand as such will have different privileges.

Note:

The majority of SELinux’s online resources focus on types. Even though the SELinux type is just the third part of an SELinux context, it is the most important one for most administrators. Most documentation will even just talk about a type such as sshd_t rather than a full SELinux context.

Take a look at the following dbus-daemon processes:

# ps -eZ | grep dbus-daemon
swift_u:swift_r:swift_dbusd_t:s0-s0:c0.c512 571 ? 00:00:01 dbus-daemon
swift_u:swift_r:swift_dbusd_t:s0-s0:c0.c512 649 ? 00:00:00 dbus-daemon
system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 2498 ? 00:00:00 dbus-daemon

In this example, onedbus-daemonprocess is the system D-Bus daemon running with the aptly namedsystem_dbusd_ttype, whereas two other ones are running with theswift_dbusd_ttype assigned to it. Even though their binaries are the same, they both serve a different purpose on the system and as such have a different type assigned. SELinux then uses this type to govern the actions allowed by the process toward other types, including howsystem_dbusd_tcan interact withswift_dbusd_t.

SELinux types are by convention suffixed with_t, although this is not mandatory.

Granting domain access through roles

SELinuxroles (the second part of an SELinux context) allow SELinux to support role-based access controls. Although type enforcement is the most used (and known) part of SELinux, role-based access control is an important method to keep a system secure, especially from malicious user attempts. SELinux roles define which types (domains) can be accessed from the current context. These types (domains) on their part define the permissions. As such, SELinux roles help define what a user (who has access to one or more roles) can and cannot do.

By convention, SELinux roles are defined with an_rsuffix. On most SELinux-enabled systems, the administrator can assign the following SELinux roles to users:

  • Theuser_rrole is meant for restricted users. This role is only allowed to have processes with types specific to end-user applications. Privileged types, including those used to switch to another Linux user, are not allowed for this role.
  • Thestaff_rrole is meant for non-critical operations. This role is generally restricted to the same applications as the restricted user, but it has the ability to switch roles. It is the default role for operators to have (so as to keep those users in their least privileged role as long as possible).
  • Thesysadm_rrole is meant for system administrators. This role is very privileged, enabling various system administration tasks. However, certain end-user application types might not be supported (especially if those types are used for potentially vulnerable or untrusted software) to keep the system free from infections.
  • Thesecadm_rrole is meant for security administrators. This role allows changing the SELinux policy and manipulating the SELinux controls. It is generally used when a separation of duties is needed between system administrators and system policy management.
  • Thesystem_rrole is meant for daemons and background processes. This role is quite privileged, supporting the various daemon and system process types. However, end-user application types and other administrative types are not allowed in this role.
  • Theunconfined_rrole is meant for end users. This role allows a limited number of types, but those types are very privileged as they allow running any application launched by a user (or another unconfined process) in a more or less unconfined manner (not restricted by SELinux rules). This role, as such, is only available if the system administrator wants to protect certain processes (mostly daemons) while keeping the rest of the system operations almost untouched by SELinux.

Other roles might exist, such asguest_randxguest_r, depending on the distribution. It is wise to consult the distribution documentation for more information about the supported roles. Theseinfocommand is the most common method to obtain an overview of available roles:

# seinfo –-role
Roles: 9
   auditadm_r
   object_r
   secadm_r
   …
   user_r

With the SELinux roles identified, let’s look at how we assign roles to users.

Limiting roles through users

An SELinuxuser (the first part of an SELinux context) is not the same as a Linux (account) user. Unlike Linux user information, which can change while the user is working on the system (through tools such assudoorsu), the SELinux policy can (and generally will) enforce that the SELinux user remains the same even when the Linux user itself has changed. Because of the immutable state of the SELinux user, we can implement specific access controls to ensure that users cannot work around the set of permissions granted to them, even when they get privileged access.

An exampleof such an access control is theuser-based access control(UBAC) feature that some Linux distributions (optionally) enable, which prevents users from accessing files of different SELinux users even when those users try to use the Linux DAC controls to grant access to each other’s files.

The mostimportant feature of SELinux users, however, is that SELinux user definitions restrict which roles the (Linux) user can assume. A Linux user is first assigned to an SELinux user, which does not need to be unique: multiple Linux users can be assigned to the same SELinux user. Once set, that user cannot switch to an SELinux role not associated with that SELinux user.

The following diagram shows the role-based access control implementation of SELinux:

resource label

SELinux users are, by convention, defined with an _u suffix, although this is not mandatory. The SELinux users that most distributions have available are named after the role they represent, but instead of ending with _r, they end with _u. For instance, for the sysadm_r role, we have the sysadm_u SELinux user.

Controlling information flow through sensitivities

The fourthpart of an SELinux context, the sensitivity, is not always present (some Linux distributions, by default, do not enable sensitivity labels, but most do). This part of the label is needed for themultilevel security (MLS)support within SELinux, whichis an optional setting. Sensitivity labels allow the classification of resources and the restriction of access to those resources based on a security clearance. These labels consist of two parts: a confidentiality value (prefixed withs) and a category value (prefixed withc).

In many larger organizations and companies, documents are labeled internal, confidential, or strictly confidential. SELinux can assign processes certain clearance levels for these resources. With MLS, we canconfigure SELinux to follow theBell-LaPadulamodel, a security model characterized byno read up, no write down: based on a process’s clearance level, that process cannot read anything with a higher confidentiality level nor write to (or communicate otherwise with) any resource with a lower confidentiality level. SELinux does not use internal, confidential, and other labels. Instead, it uses numbers from zero (the lowest confidentiality) to whatever the system administrator has defined as the highest value (this is configurable and set when the SELinux policy is built).

Categoriesallow us to assign resources with one or more categories, and to define access controls across categories. One of the functionalities resulting from using categories is to support multitenancy (for example, systems hosting applications for multiple customers) within a Linux system. Multitenancy is provided by assigning a set of categories to the processes and resources of one tenant, whereas the processes and resources of another tenant get a different set of categories. When a process does not have the proper categories assigned, it cannot touch the resources (or other processes) that have other categories assigned.

Note:

An unwritten convention in the SELinux world is that (at least) two categories are used to differentiate between tenants. By having services randomly pick two categories for a tenant out of a predefined set of categories, while ensuring each tenant has a unique combination, these services receive proper isolation. The use of two categories is not mandatory, but services such as sVirt and Docker successfully implement this methodology.

In that sense, categories are like tags, allowing us to grant access only when the tags of the process and the target resource match. As multilevel security is not often used, the benefits of onlyusing categories are persisted in what is calledmulti-category security(MCS). This is a special MLS case, which only supports a single confidentiality level (s0).

Now thatwe know how labels are used by SELinux policies, let’s look at how SELinux policies are defined and distributed.


You Might Also Like :

Back to Featured Articles on Logo Paperblog

These articles might interest you :