Developing a set of security rules is or should always be done with a common set of principles and rules in mind. This document explains the policy used by Gentoo Hardened in order to consistenly develop its security policy rules.
- 1 Principles
- 2 SELinux Domains
- 3 SELinux Roles
- 4 SELinux Packages
- 5 Coding
SELinux policy rules are used to confine applications, potentially restricting their use on a system. The rules are made to be managed by a security administrator, someone (or a group of people) who has the final say in how a system should behave. Due to the flexibility of SELinux policy rules, various different implementations exist. One can have SELinux rules allowing everything an application does, or rules that allows everything an application needs to function properly - or somewhere in between. You can confine parts of an application, or confine a group of applications. You can allow all roles to execute applications, or only a few.
In short, SELinux policy rules allow you to define the security access rules just the way you want them to be - and that's perfect. That's exactly what makes SELinux this interesting.
The problem however is that a distribution such as Gentoo Hardened offers a set of rules for a large set of users. As such, it needs to take certain decisions itself on how it defines the SELinux policy rules. And to help the developers in writing the policy rules, the same set of principles and guidelines should be followed to offer the end user an integrated, consistent set of SELinux policy rules.
That set of principles and guidelines can be found in this document. Note that this is still subject to change. For instance, if Gentoo Hardened gains sufficient developer resources it might change some principles, resulting in a change of policy.
Gentoo's policy is based upon the following set of principles. Note that principles do not mean that they are to be considered mandatory. They guide us in our definition of the policy and in handling of future events.
|Work As-Is||Confined applications should still function properly. Gentoo Hardened users who find that the policy is preventing the application to function the way it is meant to work by its developers should be able to consider this as a bug in the rules|
|Hide the Complexity||The complexity of the SELinux policy rules offered by Gentoo Hardened should be hidden from a regular user/administrator. This includes hiding denials that are considered to be harmless / cosmetic.|
|Keep It Simple||Simplicity is better. A set of rules, domains, types or roles that is easy to describe is easier to manage. This does not mean that a lower set of domains is needed! It is about being able to document and explain things quickly, and keep it flexible.|
|Be Reluctant to Trust||Applications or resources that can be influenced by untrusted actors should be individually protected. As such, they should not run in a common domain.|
|Least Privilege||Access privileges should be given on a need-to-have basis. No more, no less.|
|Track Upstream||When relying on external rules (such as offered from the reference policy) we strive to configure those rules to fit our needs or, if enhancements are needed, ensure that they do not interfere with the process of applying changes made available upstream on our repository|
Domains hold the privileges granted to an application. Designing the privileges means designing the domains and its interactions with other domains and resources.
No Role-Specific Domains
The reference policy development method supports the use of role-specific domains (like staff_mozilla_t versus user_mozilla_t ). These domains are generated automatically the moment you assign the necessary template(s) to the roles.
Although this offers a great deal of flexibility (you can have different access controls for different roles) and a more strict segregation of access controls (no single SELinux rule that potentially allows one role to influence the resources in the domain of another role, even if the real user is the same), it is more difficult to manage. Also, its flexibility already implies that the security administrator of the system customizes Gentoo Hardened's policy.
For this reason, Gentoo Hardened will not create role-specific domains by default. Exceptions are always possible. For instance, the screen_t domain uses role-specific implementations ( staff_screen_t ) because the domain needs to transition back to the caller ( staff_t to staff_screen_t which launches a shell or command in the staff_t domain).
Do Not Allow Cosmetic Denials
When developing SELinux rules, the Gentoo Hardened SELinux developers will implement the access permissions needed for an application to function properly on their system. Additional rules are then added based on testing, feedback and thorough analysis. A SELinux developer will never implement an access permission without being confident that it is needed to allow the application to function properly.
Instead, if a denial is given but seems to be cosmetic, the Gentoo Hardened SELinux developer will use dontaudit statements.
This also is one of the reasons why requests to update the policy are always accompanied with the request to show the error of the application, and not only the AVC denials, as dontaudit can be an equal solution to removing the AVC denials.
Develop desktop policies
The project will focus development on the desktop area as well. With this, we hope to create a more secure desktop environment where potential vulnerabilities in application platforms do not automatically lead to the exposure and information leakage of user documents.
This will be facilitated through support of the XDG Base Directories in the SELinux policies, and a flexible user content management selection through SELinux booleans.
Isolate context definitions
We strive to have the context definitions for an application to be part of the SELinux module. That also means that base definitions, like
lib_t are best positioned inside the file context definition of the module (unlike what the reference policy requires, which is to have those made part of the modules that define those types).
If permissions can be assigned to an application domain, support this through both an attribute-based approach as well as direct assignation.
For instance, for attribute-based:
interface(`test_client_domain',` gen_require(` attribute test_client; ') typeattribute $1 test_client; ')
For direct assignation:
interface(`test_client_domain_privs',` gen_require(` type test_log_t; type test_t; ') allow $1 test_t:process signal_perms; allow test_t $1:process signal_perms; allow $1 test_log_t:file append_file_perms; ')
The privileges in direct assignation can be assigned to the attribute then:
attribute test_client; test_client_domain_privs(test_client);
The use of this allows for attribute-based privileges on other domains, but also to assign this if the permissions are triggered through booleans:
# Outside tunable test_client_domain(foo_t) # Inside a tunable tunable_policy(`bar_is_test',` test_client_domain_privs(bar_t) ')
Assigning attributes is not possible through a
tunable_policy which is why this approach is preferred.
The move towards CIL might remove this restriction. If that is the case, this policy will be updated accordingly as we can then "just" add the attribute optionally.
Security model for services
When policy services are developed, we will keep in mind that optional use of these services could be requested. As such, when this is the case, the following security model implementations will be supported:
- system monitor
- The system monitor privilege set allows for a system domain to read various file types, system state (like sysctl values), process states, etc. It is a read-only set of privileges.
- service operator
- The service operator privilege set allows for a domain to operate all system services (init scripts)
- service administrator
- The service administrator privilege set allows for a system domain to manage the state of services as well as perform administrative commands against those services.
- software administrator
- The software administrator privilege set allows for a system domain to manage various file types (but not, or only in a very controlled manner, security sensitive files). The software administrator can transition to package management tools and invoke administrative commands needed to finalize software installation.
- system state administrator
- The system state administrator privilege set allows for system state handling, including sysctl values, network configuration settings, etc.
- system security administrator
- The security administrator privilege set allows for security-sensitive types to be managed, including SELinux policy.
Such privilege sets would be used for system domains to differentiate what they can do, and would benefit things like configuration management tooling. The differentiation is needed in order to support the use of particular services for a specific reason, without using very broadly defined policies to match all possible use cases.
It results in the following SELinux booleans for such tooling:
- Read and monitor system files and system state
- Manage system services (runtime state)
- Manage and administer services
- Manage non-security-sensitive files and resources
- Manage system state and networking
- Manage security-sensitive files and SELinux policy
In Gentoo Hardened, the supported roles as defined as follows.
First, the set of refpolicy-provided roles:
- The auditadm_r role is meant to provide administrative access to the audit subsystem.
- The logadm_r role is meant to provide management privileges to the system logs and logging infrastructure (non-audit).
- The secadm_r role is meant to provide management privileges to the SELinux policy.
- The staff_r is for unprivileged system access, but for users who are able to switch roles.
- The user_r is for unprivileged system access, for users not able to switch roles.
- The sysadm_r is for full system administrative access.
- The unconfined_r role is an unconfined role.
Additionally, the following roles are not provided through refpolicy, but supported in Gentoo as well:
- The dbadm_r role is for database administrative roles.
- The webadm_r role is for web application administrative roles.
- The guest_r role is a very limited, unprivileged non-graphical user role.
- The xguest_r role is a very limited, unprivileged graphical user role.
Unprivileged user domains
Of the unprivileged user domains, the following principles apply...
The guest_r and xguest_r roles are as limited as possible, only providing basic logon services and system interaction. Any additional application support within the roles should be added by the administrator.
The staff_r and user_r roles should resemble each other as much as possible (with the same privileges), except for the role changing privileges that are assigned to the staff_r role. Also, all applications that might need to be supported on the roles should be added in. Administrators should have little need to add in additional application role support for these user domains (as long as the applications are of an unprivileged nature).
The unconfined_r role (with the unconfined_t user domain) should not transition to other (confined) domains.
Privileged user domains
The sysadm_r role is meant to provide a full system administrative role, including SELinux policy support, log administration, (all) services and more.
Service-specific roles are made available for the administrator as well, allowing him to differentiate users based on their functional role. These roles are
- the secadm_r role for security policy administration (in case this should be limited)
- the logadm_r and auditadm_r roles for logging and audit administration
- the dbadm_r and webadm_r roles as example privileged roles for specific services (in this case databases and web application administration)
Name SELinux policy packages after their module
SELinux policy packages should be called after the module they implement (and not the Gentoo package for which the policy would be implemented). The name should use the sec-policy/selinux-<modname> syntax.
By using the upstream module name, we ensure that no collisions occur (neither package name collisions as well as file collisions during installations) and follow upstream strictly. It also keeps the naming of the packages clean.
To support development by a team, a coding style document has been drafted up.