The example security server implements a security model that is a combination of a Type Enforcement (TE) model, a Role-Based Access Control (RBAC) model, and optionally a Multi-Level Security (MLS) model. The TE model provides fine-grained control over processes and objects in the system, and the RBAC model provides a higher level of abstraction to simplify user management. The optional MLS model is not (yet) documented in this report. This section describes the TE and RBAC models, and then discusses the concept of user identity in SELinux.
A traditional TE model binds a security attribute called a domain to each process, and it binds a security attribute called a type to each object. The traditional TE model treats all processes in the same domain identically and it treats all objects that have the same type identically. Hence, domains and types can be viewed as security equivalence classes. A pair of access matrices specify how domains can access types and how domains can interact with other domains. Each user is authorized to operate in certain domains.
A TE model supports strong controls over program execution and domain transitions. A program, like any other object, is assigned a type, and the TE access matrix specifies what types can be executed by each domain. Furthermore, the TE access matrix specifies what types can be executed to initially enter a domain. Hence, a domain can be associated with a particular entrypoint program and optionally with particular helper programs and/or shared libraries. This characteristic of TE is useful in associating permissions with a particular set of code based on its function and trustworthiness and in protecting against the execution of malicious code.
The SELinux TE model differs from the traditional TE model in that it uses a single type attribute in the security context for both processes and objects. A domain is simply a type that can be associated with a process. A single type can be used both as the domain of a process and as the type of a related object, e.g. the /proc/PID entries for a process. A single access matrix specifies how types can access or interact with other types in terms of the permissions defined by the Flask architecture. Although the example TE configuration often uses the term domain when referring to the type of a process, the SELinux TE model does not internally distinguish domains from types.
The SELinux TE model also differs from the traditional TE model in that it uses the security class information provided by the Flask architecture. A SELinux TE transition or access decision is based on a type pair and on the security class. Hence, the policy can treat objects that have the same type but different security classes differently. For example, the policy can distinguish a TCP socket created by a domain from a raw IP socket created by the same domain.
A third difference between the SELinux TE model and the traditional TE model is that the SELinux TE model does not directly associate users with domains. Instead, SELinux uses the RBAC model to provide an additional layer of abstraction between users and domains. This approach is discussed further in the next subsection.
A TE transition rule for a process specifies the new domain based on the current domain of the process and the type of the program. A TE transition rule for an object specifies the new type based on the domain of the creating process, the type of the related object, and the object security class. If no matching rule is found in the TE configuration, then the SELinux TE model provides a default behavior appropriate for the class of object. For a process, the domain of the process is left unchanged across the program execution. For an object, the type of the related object (e.g. the parent directory for files) is used for the new object.
A TE access vector rule specifies an access vector based on the type pair and object security class. Rules can be specified for each kind of access vector, including the allowed, auditallow, and auditdeny vectors. These access vector rules define the TE access matrix. If no matching rule is found in the TE configuration, then the SELinux TE model defines a default behavior for each kind of access vector. Permissions are denied unless there is an explicit allow rule. No permissions are audited when granted unless there is an explicit auditallow rule. Permissions are always audited when denied unless there is an explicit dontaudit rule.
A traditional RBAC model authorizes users to act in certain roles, and assigns a set of permissions to each role. The SELinux RBAC model authorizes each user for a set of roles, and authorizes each role for a set of TE domains. A role dominance relationship can optionally be specified in the RBAC configuration to define a hierarchy among roles. The assignment of permissions is primarily deferred to the TE configuration. This approach combines the ease of management provided by the RBAC model with the fine-grained protections provided by the TE model.
The SELinux RBAC model maintains a role attribute in the security
context of each process. For objects, the role attribute is typically
set to a generic
object_r role and is unused.
Role transitions for processes are controlled through a combination of
the RBAC and TE models. The RBAC configuration specifies authorized
transitions between roles based on the pair of roles. However, it is
also desirable to limit role transitions to certain programs to ensure
that malicious code cannot cause such transitions. Hence, role
transitions are typically limited to certain TE domains in the policy
The Linux user identity attributes are unsuitable for use by SELinux. Linux uids are often changed simply to express a change in permissions or privileges as opposed to a change in the actual user, posing problems for user accountability. Linux uids can be changed at any time via the set*uid calls, providing no control over the inheritance of state or the initialization of the process in the new identity. Linux uids can be arbitrarily changed by superuser processes.
Rather than imposing new restrictions on the Linux user identity attributes, SELinux maintains a user identity attribute in the security context that is independent of the Linux user identity attributes. By using a separate user identity attribute, the SELinux mandatory access controls remain completely orthogonal to the existing Linux access controls. SELinux can enforce rigorous controls over changes to its user identity attribute without affecting compatibility with Linux uid semantics.
The policy configuration limits the ability to change the SELinux user identity attribute to certain TE domains. These domains are associated with certain programs, such as login, crond and sshd, that have been modified to call new library functions to set the SELinux user identity appropriately. Hence, user login sessions and cron jobs are initially associated with the appropriate SELinux user identity, but subsequent changes in the Linux uid may not be reflected in the SELinux user identity. In some cases, this is desirable in order to provide user accountability or to prevent security violations. In some distributions that have integrated SELinux support, the su program also changes the SELinux user identity to the new user identity, while other distributions leave the SELinux user identity unchanged by su.
Since the SELinux user identity is independent of the Linux uid, it is possible to maintain separate user identity spaces for SELinux and Linux, with an appropriate mapping performed by the programs that set the SELinux user identity. For example, rather than maintaining a separate entry for each Linux user in the SELinux policy, it may be desirable to map most Linux users to a single SELinux user that is unprivileged. This approach is suitable when it is not necessary to separate these users via the SELinux policy.