Gentoo SELinux Handbook
Content:
-
Introduction to Gentoo/Hardened SELinux
In this part we cover what SELinux is and how it is positioned within the
Gentoo/Hardened project.
-
Enhancing Linux Security
Security is more than enabling a certain framework or installing a different
Linux kernel. It is a way of working / administrating your Gentoo Linux system.
We cover a few (generic) best practices, and then elaborate on what Mandatory
Access Control is and how SELinux fills in this gap.
-
SELinux Concepts
To be able to properly work with SELinux, it is vital that you understand a few
of its concepts like domains, domain transitions and file contexts. Without
a basic understanding of these aspects, it will be difficult to understand
how SELinux policies work and how to troubleshoot if things go wrong.
-
SELinux Resources
To get more acquainted with SELinux, many resources exist on the Internet.
In this chapter we give a quick overview of the various resources as well
as places where you can get more help when you are fighting with SELinux.
-
Using Gentoo/Hardened SELinux
With the theoretic stuff behind us, let us start by installing Gentoo/Hardened
with a SELinux kernel as well as the SELinux tools.
-
Gentoo SELinux Installation / Conversion
To set up SELinux within Gentoo/Hardened, you first need to install Gentoo with
the correct Hardened profile (or convert to the Hardened profile) and then
update your system to become a SELinux-managed system. This chapter will guide
you through this process.
-
Configuring SELinux For Your Needs
With SELinux now "installed" and enabled (although in permissive mode), we now
configure it to suit your particular needs. After all, SELinux is a Mandatory
Access Control system where you, as security administrator, define what is
allowed and what not.
-
SELinux Commands
Let's take a step back and get to know a few more commands. We covered most of
them in the previous section, but we will now dive a bit deeper in its
syntax, features and potential pitfalls.
-
Permissive, Unconfined, Disabled or What Not...
Your system can be in many SELinux states. In this chapter, we help you switch
between the various states / policies.
-
Modifying the Gentoo Hardened SELinux Policy
Gentoo Hardened offers a default policy, but this might not allow what you want
(or allows too much). In this chapter we tell you how you can tweak Gentoo's
policy, or even run your own.
-
Troubleshooting SELinux
Everything made by a human can and will fail. In this chapter we will try to
keep track of all potential issues you might come across and how to resolve
them.
-
Change History
As documentation evolves with the technology, this handbook too sees its fair
share of changes. To allow users, who are already on SELinux, to verify if there
are any changes they need to be aware off, this chapter lists the changes in
chronological order.
A. Introduction to Gentoo/Hardened SELinux
1. Enhancing Linux Security
1.a. Introduction
A Warm Welcome
Welcome to the Gentoo SELinux handbook. In this resource, we will bring you up
to speed with Gentoo Hardened's implementation of SELinux and the policies
involved. Part of this exercise is to help you understand why SELinux was
brought to life and which concept is behind the development of the SELinux
patches. We will cover the SELinux concepts, the reference policy that Gentoo
Hardened uses and elaborate on how to work with the various SELinux tools.
The purpose of this book is not to explain SELinux itself in great detail. There
are many references available on the Internet and in the better bookstores that
help you with the SELinux topic. Instead, we will focus on SELinux integration
within Gentoo Hardened. Of course, we will give a quick introduction to SELinux
to allow you to understand how it works, what it is and help you identify which
actions you will need to take in order to properly secure your system using the
SELinux tools.
1.b. Securing Linux
Security In General
Security is often seen as a vague concept. What is security in general? How do
you measure security? What is the benefit and how do you make sure you do not
put too much effort in securing your system?
Well, security zealots will tell you that there is no such thing as too much
security. If properly implemented, security does not restrict functionality or
performance. It does not give you too much overhead in order to do your tasks.
But implementing security properly is a different and time-consuming task. That
is also why you often hear that security is as good as its administrator.
So, how can you look at security? A good practice on security is to define your
security goals. List what you want to achieve and why. By tracking the threats
that you want to minimize, you build up a security model that is appropriate for
your environment. Such threats can be very broad, such as "Ensure no-one is able
to work around our security measures".
In case of a Linux system powered with SELinux, this would at least mean that
you want to protect critical system files, such as kernel image(s) and boot
loader configuration, passwords and the SELinux policy binary itself from being
written by anyone or anything except trusted processes.
Access Control
A decent access control system (or group of systems) ensures that only
authorized individuals or processes are granted access to the resources they are
tring to work with.
Before one can implement an access control system, you first need to have proper
authentication in place. If your authentication schemes are flawed, your access
control system might not be able to differentiate legitimate users from
malicious ones.
Authenticating users within Linux is often done through PAM (Pluggable
Authentication Modules), a powerful mechanism to integrate multiple
low-level authentication schemes into a high-level interface.
Authorizing access to resources however is often done through a simple
permission scheme. Most resources are not hidden by default, although
patches and updates exist (such as those offered by Gentoo Hardened's
kernel sources with grSecurity patches which includes support for this
kind of measures). File-system wise, you can hide the existence of files
by ensuring the directory in which the file resides is not readable nor
"executable" by unauthorized accounts.
This default permission scheme has major drawbacks. It does not allow you to
define very flexible authorizations (it only allows permissions on three levels:
owner, group-owner and everybody else) and is limited to read/write/execute
rights (although a few additional attributes are supported nowadays as well).
Another drawback is that the permission scheme is discretionary, meaning
that users and processes are able to change the security policy in place.
For the majority of uses, this permission scheme is sufficient and has proven to
offer a decent method for managing access authorizations. But the drawbacks have
shown to be a major hole in the Linux' offering.
1.c. Mandatory Access Control
Enter SELinux
If the above mentioned discretionary access control, abbreviated to DAC,
is not sufficient (and if you are keen on security, you will not find it
sufficient), you need a Mandatory Access Control, or MAC system.
When using a MAC system, activities that a process wants to perform on another
resource need to be explicitly allowed. It offers a higher granularity on
permissions as well as resources. They often support not only files, but also
sockets, ports, memory segments, queues, processes, kernel services, system
calls, devices, file systems and more. The granularity of activities supported
is also quite large. For files, this can be append, create, execute, write,
link, ioctl, get- and setattr, read, rename, lock, ... whereas for sockets this
might be append, bind, connect, create, write, sendto, accept, ... Also, when
using a MAC system, no user or process can manipulate the security policy
itself: what the security administrator has defined cannot be overturned.
This is where SELinux comes to play. SELinux is a Linux kernel feature which
implements, amongst other things, a MAC system for controlling and governing
access to various resources. It uses a deny-by-default permission scheme, so any
access that a process wants to perform needs to be explicitly granted.
SELinux also allows you to put a finer-grained permission model on top
of the traditional DAC system (which is still in use when using SELinux
- in other words, if the traditional system does not allow certain activities,
it will not be allowed even if there are SELinux policies granting the
permission).
What is SELinux
To support this finer-grained permission model, you would think that changes
are needed to the Linux kernel. Yet thanks to the Linux kernel LSM
interface (Linux Security Modules), support for SELinux was easily added
and since the 2.6 kernel series, SELinux has been integrated in the mainstream
kernel release. But supporting SELinux and using SELinux are very different topics.
In order to properly identify resources, SELinux needs to assign labels to these
resources. When the resources are in-memory, this is mostly supported by the
Linux kernel itself, but for persistent resources such as files, these labels
need to be placed somewhere. SELinux has chosen to use a file's extended
attributes (which is stored on the file system itself). The advantage here is
that a label remains on the file even if the file is renamed. A disadvantage of
this approach is that the file system must support extended attributes,
which not all file systems do (or have activated).
SELinux also uses roles to govern resource access. A user that does not have
access to the system administration role should never be allowed to execute any
system administration activities even if he is able to escalate its privileges
(say through a set-uid application). To support roles, SELinux requires changes
to the authentication services (PAM) and needs to store role definitions and
authorizations somewhere.
Next to the kernel support and labels assigned to the resources and support
within the authorization system, SELinux also requires particular tools to
support the SELinux features. Examples are administrative tools to view and
manipulate labels, privilege management tools (like sudo), system
services (like SysVInit) etc. This is reflected in a set of patches
against these (and more) tools which are not always part of the applications'
main source code.
Gentoo Hardened and SELinux
What Gentoo Hardened offers is SELinux integrated in the distribution. When you
select SELinux support, Gentoo Hardened will apply the necessary patches against
the applications and help you (re)label your files and other resources to become
SELinux-manageable. Gentoo Hardened also integrates SELinux support inside
Portage, allowing for newly installed files to be automatically labeled and to
use a SELinux-supporting sandbox environment for
safe package building.
Next to the pure technological support, we hope that you will also find the
necessary supporting documents, guides, experience and on-line support for using
SELinux within Gentoo. Never hesitate to come and say hi on the
#gentoo-hardened chat channel in the Freenode IRC network or on our
mailing lists.
If you believe that SELinux is the right thing for you and you want to try it
out using Gentoo Hardened, please read on. The next chapter will inform you how
SELinux security is "designed" and how it is conceptually structured. Further
chapters will then help you with the authorization language and the "base"
policies that most distributions start from, and finally help you install,
run and manage a SELinux hardened Gentoo system.
2. SELinux Concepts
2.a. Introduction
SELinux Concepts
Since SELinux is a MAC system, you should already figure out that managing
SELinux-based permissions and rights might be a bit more challenging than
managing the discretionary access control rights generally used on a Linux
system. What is more is that SELinux works on top of the DAC system
everybody is used from Linux. As a system administrator, you will need to be
acquainted with some of the concepts and structures that SELinux has put in
place in order to manage the access on the SELinux system.
Describing those concepts is the purpose of this particular chapter. We will
give examples on the various concepts from a SELinux enabled Gentoo Hardened
system. However, do not fear if the use of particular commands is not explained
sufficiently. They are currently meant as examples (their output is more
important) and will be discussed further in this document.
SELinux Policies
Within Gentoo (and other distributions as well), SELinux is supported through
several policy levels. These are, in climbing order of complexity (meaning they
can offer more security, but are harder to manage):
-
targeted is a policy where network-facing services (daemons) are
confined (the processes can only execute those actions that are defined
in the policy), but other applications are running what is called
unconfined, meaning that there are little to no restrictions for
those processes.
-
strict is a policy where all processes are confined. There are no
unconfined domains. In other distributions, this is still considered the
targeted policy but without the unconfined domain definition.
-
multi-category security is a policy where the (confined) domains can
be categorized (split up), allowing for multiple processes running in
different instances of a confined domain
-
multi-level security is a policy where rules exist regarding the
sensitivity of domains and resources. This allows for a "proper"
information flow policy (make sure that sensitive data isn't leaked
to less privileged domains). Conceptually, one can understand this best
if one considers sensitivity levels of Public, Internal, Confidential,
Strictly Confidential, etc.
When using Gentoo Hardened, all these policies are available. However,
development focuses mainly on strict and mcs. The
targeted policy is assumed to work if strict works whereas we know
that the mls policy is currently not fit yet for production use.
Note:
To clear up some confusion, especially when trying to seek support outside
Gentoo: our "strict" implementation is not what was "strict" up to the year
2008. The old meaning of strict involved a different implementation of the
policy.
|
2.b. Security Contexts
Users, Roles, Domains, Sensitivities and Categories
One of the first concepts you will need to be acquainted with is the concept of
a security context. This is a state given to a resource that uniquely
identifies which grants (permissions) are applicable to the resource. This
context is extremely important for SELinux as it is the definition on which it
bases its permissions (grants or denials). When a resource has no security
context assigned, SELinux will try to give it a default security context which -
in the spirit of lowest privilege - has little permissions to perform any actions.
Within SELinux, such a security context is displayed using three to five
definitions, depending on the type of policy you are running:
- user
-
This is the SELinux user (which is not the same as the Linux/Unix
technical user) assigned to the resource
- role
-
This is the SELinux role in which the resource currently works
- type
-
This is the type assigned to the resource and is the key to SELinux'
enforcement rules
- sensitivity
-
This is a level given to a resource informing the system about the
sensitivity of this resource. A sensitivity is something akin to
Public, Internal, Restricted, Confidential, Strictly Confidential, ...
Sensitivity levels are only supported in MLS policies.
- category
-
This is a specific instantiation of a resource. It allows segregation of
resources even if they are of the same type. More about categories later -
categories are supported in MLS and MCS policies.
More information on these particular definitions is given throughout the
remainder of this chapter.
As an example let's take a look at the security context of a logged on user:
Code Listing 2.1: Getting the security context of a logged on user |
~$ id -Z
staff_u:staff_r:staff_t
|
In this case, the user is identified as the SELinux user staff_u,
currently in the staff_r role and assigned to the staff_t
type. The actions the user is allowed to do are based upon this security
context. Also, you notice that only three identifiers are shown. This is
because the example is taken on a strict (or targeted) policy
system. The next example gives the same result, but on an MCS policy
system.
Code Listing 2.2: Getting the security context of a logged on user on an MCS policy system |
~$ id -Z
staff_u:staff_r:staff_t:s0-s0:c0.c1023
|
Here, the user is running with sensitivity level of s0 (which, in an MCS policy
system, is the only available sensitivity) and with a category set of c0 up to
and including c1023. However, note that in an MCS policy system categories are
optional, so you might just see an output of staff_u:staff_r:staff_t:s0.
Access Control Policy
As mentioned before, these security contexts are used as the base for the
permission rules. What SELinux does is check the security context of the source
(for instance a process) and the destination (for instance a file that that
process wants to read). It then checks if the requested operation (read) is
allowed between those two contexts. Keep in mind though that SELinux works on
top of the standard permission system used by Linux. If a process is not able to
read a file to begin with, SELinux is not even consulted.
Now, where the security context defines the state of a resource, we have not
spoken about the resources themselves. Within SELinux, the resource types are
defined as object classes. Common examples are file or dir,
but SELinux also manages classes such as filesystem, tcp_socket,
process, sem (semaphores) and more.
On each object class, a set of permissions is declared which are possible
against a resource within this object class. For instance, the process
object class supports at least the following permissions:
Code Listing 2.3: Supported permissions against a 'process' resource |
~# ls /selinux/class/process/perms
dyntransition getcap rlimitinh setpgid siginh
execheap getpgid setcap setrlimit sigkill
execmem getsched setcurrent setsched signal
execstack getsession setexec setsockcreate signull
fork noatsecure setfscreate share sigstop
getattr ptrace setkeycreate sigchld transition
|
The most common SELinux access control rule (allow) is described as
follows:
Code Listing 2.4: SELinux allow statement |
allow ACTOR TARGET:CLASS PRIVILEGE;
+-+-+ +-+--+ +-+-+ +---+---+
| | | `- Permission to be granted (like "write")
| | `- Class on which permission is given (like "file")
| `- Resource (label) on which permission is valid (like "portage_conf_t")
`- Actor (domain) which gets the privilege (like "sysadm_t")
|
Let's take a look at a small example to explain the permission rules and how
SELinux uses them. The example user is in the staff_u:staff_r:staff_t
context and wants to write to its own home directory. As we can expect, this
should be allowed. Don't worry about the commands here, we'll discuss them more
properly further in this document.
Code Listing 2.5: Seeing if a user can write to its own home directory |
~$ ls -dZ ${HOME}
staff_u:object_r:user_home_dir_t /home/swift
~$ sesearch -s staff_t -t user_home_dir_t -c dir -p write -A
Found 1 semantic av rules:
allow staff_t user_home_dir_t : dir { ioctl read write create ... };
|
As expected, the security context of the user (to be more specific, the domain
in which it resides) has write access to the domain of the target's directories.
The notion of domain is frequently used in SELinux documentation and
refers to the type assigned to a process. BTW, as files do not have roles,
they are given the default object_r role by SELinux.
Now take a look at the following example. Our user, who is inside the portage
group, wants to write to the /var/tmp/portage directory:
Code Listing 2.6: Seeing if a user can write to the /var/tmp/portage directory |
~$ id -a
uid=1001(swift) gid=100(users) groups=100(users),...,250(portage),...
~$ ls -ldZ /var/tmp/portage
drwxrwxr-x. 3 portage portage system_u:object_r:portage_tmp_t 4096 Dec 6 21:08 /var/tmp/portage
|
From the standard Linux permissions, the user has write access. But does SELinux
also grant it?
Code Listing 2.7: Trying to write into /var/tmp/portage |
~$ sesearch -s staff_t -t portage_tmp_t -c dir -p write -A
~$
~$ touch /var/tmp/portage/foo
touch: cannot touch '/var/tmp/portage/foo': Permission denied
|
As SELinux could not find a rule that allows the staff_t domain to write to any
directory labeled with the portage_tmp_t type, the permission was denied.
2.c. Type Enforcements / Domain Types
Types and Domains
To explain how the permission rules work and how this is enforced through the
security contexts, let's start from the last definition in the context (the
type) and work our way forward through the roles and users.
-
A SELinux type is a particular label assigned to a resource. The
passwd command for instance is labeled with the passwd_exec_t type.
-
A SELinux domain is the security state of a process and identifies the rights
and permissions it has. It is most often referred to by its type declaration.
For instance, for a running passwd command, its domain is passwd_t.
The rules that identify the allowed actions for a domain have been described earlier. Again:
Code Listing 3.1: Standard SELinux policy rules |
allow <src_domain> <dst_type> : <class> { permission [ permission [ ... ] ] } ;
|
An example for the passwd_t domain would be the permissions granted
between the passwd_t domain and the shadow_t type (used by the
/etc/shadow file).
Code Listing 3.2: Grants between passwd_t and shadow_t |
allow passwd_t shadow_t : file { ioctl read write create ... } ;
|
This permission syntax is very powerful, but also difficult. To have a secure
system where normal behavior is allowed, you need to seriously fine-tune these
rules for each and every application (and thus domain) that your system wants to
host. Giving too broad permissions to a domain on a particular type might result
in unauthorized activity being granted. Giving too few permissions might result
in loss of efficiency or even effectiveness.
To support easier grant rules, SELinux allows grouping of types using type
attributes. For instance, the attribute exec_type bundles all types
that are assigned to executable files (such as bin_t, ssh_exec_t,
...), whereas the file_type attribute bundles all types that are
assigned to regular files. Although this can simplify rule management, it makes
it easier to grant too many permissions.
Domain Transitions
So far for types, domain definitions and their permissions. We have stated before
that permissions are based on the domain in which a process resides. But how
does a process become part of the domain? You might think that this happens by
default (starting the passwd command would automatically bring the
process in the passwd_t domain), but this is in fact a combination of
three specific privileges that need to be granted:
-
The current domain must be allowed to transition to a domain
-
The target domain should have an entry point, which is an executable
that is allowed to start in the domain
-
The source domain should have execute rights on (the domain of) that
executable
Important:
Not being allowed to transition does not mean that you cannot
execute the binary. The binary can still be executed, but will not run inside
the target domain. Instead, it will inherit the domain of the executor and hence
the rights and permissions of this domain.
|
Through these rules, the security administrator of a system can more
specifically control who and under which conditions particular actions can be
taken.
2.d. Roles and Rights
The Role of a Role
The previously discussed domains and domain rules is quite powerful. However,
this is not where SELinux stops. After all, you want to be able to deny access
towards particular domains from unauthorized users. One requirement is of course
not to allow transitions from the user domain to that restricted domain, but how
can you enforce one set of users to be allowed and another to be denied?
Enter the roles. By using roles, you can tell SELinux which domains are allowed
for a role and which aren't. An example would be the ifconfig_t domain.
This domain has the rights to change the networking interface definitions - not
something you want to allow your users. And in fact, if you would verify,
SELinux does not allow the user role user_r to be assigned with the
ifconfig_t domain.
Code Listing 4.1: ifconfig_t domain and user_r versus sysadm_r |
~$ seinfo -ruser_r -x
user_r
Dominated Roles:
user_r
Types:
...
~$ seinfo -rsysadm_r -x
sysadm_r
Dominated Roles:
sysadm_r
Types:
...
ifconfig_t
...
|
Important:
Again, not being able to be associated with a domain does not mean that the
user_r role cannot execute the ifconfig binary. It can, but
it will execute the binary within its own domain (user_t) and as such
will not have the rights to manipulate the networking interface (but will still
be able to read the interface information albeit with limited output).
|
Roles are often used in access control systems to group permissions to a single
functional set (the role) which can then be assigned to individuals (accounts).
For instance, such access control systems create roles for accountants,
operators, managers, ... and grant the appropriate privileges to these roles.
Then, their users are assigned one (or sometimes multiple) roles and the users
inherit the permissions assigned to these roles.
With SELinux, the idea remains the same (use roles to functionally differentiate
privileges) but is implemented differently: roles are assigned target domains
in which a role is allowed to "be in". The permissions remain assigned to the
domains.
Role Transitions
Users (and processes) have the ability to switch roles. This is allowed by
SELinux, but of course only when the switch itself is granted. By default,
the SELinux policy used by Gentoo Hardened offers five roles on a SELinux
system:
- object_r
-
The object_r role is the only role by default available through
SELinux. It is usually only assigned to resources where roles have no
benefit or value (such as files and directories).
- system_r
-
The system_r role is used for highly privileged system services.
The system_r role is allowed to switch to any other "default" role.
No role exception sysadm_r can switch to the system_r role.
- sysadm_r
-
The sysadm_r role is used for system administration activities. The
sysadm_r role is allowed to switch to any other "default" role. Only
the system_r and staff_r roles are allowed to switch to the
sysadm_r role.
- staff_r
-
The staff_r role is used for system operators who might have the
rights to perform system administration tasks. The staff_r role is
only allowed to switch to the sysadm_r role. Only sysadm_r and
system_r can switch to the staff_r role.
- user_r
-
The user_r role is used for standard, unprivileged users. It is not
allowed to transition towards any other role; only sysadm_r and
system_r roles are allowed to switch to the user_r role.
Note:
A "default" role is any of user_r, staff_r, sysadm_r or
system_r. If you create additional roles yourself, they are not part of
the "default" roles.
|
Using these definitions, a user inside the user_r role will never be able
to execute ifconfig within the ifconfig_t domain. The use of the
word never here is important: not even if the user is able to become
root using sudo or any other command will he be able to run the
ifconfig command in the ifconfig_t domain because, even after
running sudo, he is still inside the user_r role.
SELinux Users
A SELinux user is not the same as the Linux user. Whereas standard Linux user
accounts can be switched using commands such as su or sudo, a
SELinux user can not be changed. Even when you successfully execute sudo,
your SELinux user will remain the same.
When you look at a SELinux powered system, you might notice that that system
doesn't use many SELinux users. For instance, Gentoo Hardened's default setup
defines the users root, user_u, staff_u, sysadm_u and
system_u and some systems never introduce any other SELinux user. But if
that is the case, is the above advantage of SELinux users (once a user is logged
on, he cannot change his SELinux user) the only one?
Well, no. SELinux users are also used to categorize accounts which have the
permission to use a particular role.
Code Listing 4.2: SELinux users and their associated roles |
~# semanage user -l
SELinux User SELinux Roles
root staff_r sysadm_r
staff_u staff_r sysadm_r
sysadm_u sysadm_r
system_u system_r
user_u user_r
|
Standard Linux users are mapped to these SELinux users:
Code Listing 4.3: Linux users and their SELinux user mappings |
~# semanage login -l
Login Name SELinux User
__default__ user_u
root root
swift staff_u
|
In this example, only logins of the Linux user swift (through
staff_u) and root (through the root SELinux user)
will be able to eventually run inside the sysadm_r role. All other
Linux accounts will be by default mapped to the user_u user (and
this user_r role).
This is only applicable for interactive logins. Processes that are
launched through an init script or otherwise do not automatically become part of
the SELinux user user_u: depending on the security context of whatever
process is starting them, they can become anything. Of course, if the security
context of the process that is starting them is user_u:user_r:user_t then
they will not be able to transform into anything other than
user_u:user_r:* with * a domain supported by the user_r
role.
SELinux users are also used to implement User Based Access Control or
UBAC. This SELinux functionality allows for domains to be SELinux user
aware: a process running in the context of a particular SELinux user can then -
for instance - only work with files of the same SELinux user. This offers a
finer grained access method, because that process might run within a domain
which has write access to the domain of the file, but can still not write to the
file because the SELinux users' differ.
At this moment, Gentoo Hardened SELinux' supports both policies with and
without UBAC, although we strongly recommend to use UBAC. This is controlled
through the ubac USE flag.
2.e. Multi Level Security / Multi Category Security
Introduction
Next to the type enforcement feature, SELinux also offers MLS and MCS support.
This allows administrators to define a hierarchical confidentiality policy.
For instance, you can ensure that a user or process within a certain
security domain and level can write to files with the same level (or higher), or
read files with the same level (or lower), but not write files to a lower level.
This allows administrators to implement some sort of
public/internal/confidential/strictly confidential hierarchical security level
for files.
Although implementation of MLS is possible with the type enforcement rules we
have previously explained, it would lead to an unmanageable collection of types
and permissions. The MLS implementation simplifies this.
Multi-Level Security
The most flexible - but also most challenging to manage - method offered by
SELinux is MLS, or Multi-Level Security. When using this policy type,
security administrators can assign sensitivity labels to resources and define
which domains (and which sensitivity levels) are able to read/write to which
level. A level is always given as a range, showing the lowest and highest level
that a particular domain is running in.
Next to the sensitivity level, MLS supports categories on a per-level basis.
These categories allow the security administrator to make different, possibly
independent "containers" for sensitive resources. To give an example, the
administrator can support the levels Public up to Strictly Confidential, and
categories of "Finance", "Risk Analysis", "Acquisitions", "IT Systems", ...
With such categories, one can then allow one role to have access to all
sensitivity levels for a particular category (say "IT Systems") but still only
have access to the Public and Internal documents of all other categories.
Multi-Category Security
The MCS or Multi-Category Security policy is a subset of the MLS policy.
It supports the various categories, but without using the multiple security
levels for the resources.
The use of MCS has become popular because it is far less difficult to manage
while still retaining some of the flexibilities offered by the MLS policy.
Where MLS is more chosen for business purposes (and as such has some influence
on the organization of the business), MCS is often used for multitenancy
architectures. In a multi-tenant architecture, systems are running processes for
various clients simultaneously. Categorisation allows for separation of
privileges across these processes without introducing multiple domains (which
would require the development of new policies for each new client that a system
wants to serve).
2.f. Reference Policy
About refpolicy
As described previously, SELinux uses type enforcement to describe the state of
your system. This is done by giving each resource on your system (be it a
process, a network port, a file or directory) a specific type and describe the
rules how types can work with each other.
Managing such a policy is not easy. Unlike some other MAC systems, which rely
on a learning mode and do not use domain definitions (they rather keep track of
which commands a process is allowed to execute), a proper SELinux definition
requires lots (thousands and thousands) of permission lines.
To ensure that no duplicate effort is made, and to help distributions like
Gentoo, Fedora, RedHat, Debian, ... with their SELinux integration efforts, a
project is launched called The Reference Policy.
This project, managed by Tresys, is used by almost
all SELinux supporting distributions, including Gentoo Hardened, Fedora, RedHat
Enterprise Linux, Debian, Ubuntu and more. This implementation not only offers
the modular policies that users are looking for, but also enhances the SELinux
experience with additional development tools that make it easier to work with
the SELinux policies on your system. Updates in the reference policy eventually
make it in all supported distributions. The same goes for Gentoo Hardened, which
aims to use a policy as close as possible to the reference policy, and submits
its own patches to the reference policy as well, which benefits the entire
community.
Reference Policy API
One major advantage of the reference policy is its API. To help policy writers,
the reference policy uses a macro language which generates the necessary allow
(and other) rules. This macro language makes it a lot easier to add rights to
particular domains. You can find the API documented online, but if you have
USE="doc" set, it will be stored on your system as well the moment you install
and configure SELinux.
Modular Approach
Another feature of the reference policy is its use of modules. If you
would build all rules in a single policy (a binary file readable by the Linux
kernel, allowing it to interpret and enforce SELinux rules), the file would
quickly become too huge and inefficient.
Instead, the reference policy defines the rules in what it calls modules, which
define one domain (like portage_t) or more (if they are all tightly
related) and the rights and privileges that that domain would need in order to
function properly. Any right that the domain needs with respect to another
domain needs to be defined through that domains' interfaces (see earlier),
forcing the modules to be specific and manageable.
Code Listing 6.1: Example overview of installed SELinux modules |
# semodule -l
alsa 1.11.0
apache 2.3.0
audioentropy 1.6.0
dbus 1.15.0
dmidecode 1.4.0
|
By using a modular approach, one only needs to load the base policy (kernel
layer as well as other, core definitions) and the modules related to his system.
You can then safely ignore the other modules. This improves performance (smaller
policy, which also causes rebuilds to be a lot less painful) and manageability
(properly defined boundaries for policy rules).
Tunables and Conditionals
But wait, there's more. The reference policy also supports booleans.
Those are flags that a security administrator can enable or disable to change
the active policy. Properly defined booleans allow security administrators to
fine-tune the policy for their system.
Code Listing 6.2: Overview of available booleans |
# getsebool -a
allow_execheap --> off
allow_execmem --> off
allow_execmod --> off
allow_execstack --> off
allow_gssd_read_tmp --> on
allow_httpd_anon_write --> off
|
Booleans are an important part to make a generic reference policy which is still
usable for the majority of SELinux users. Although they have specific
requirements (such as allowing ptrace, or disallowing execmem) they can still
use the same reference policy and only need to toggle the booleans they need.
Policy Files and Versions
The SELinux policy infrastructure that is used (i.e. the capabilities and
functionalities that it offers) isn't in its first version. Currently, SELinux
deployments use a binary version of 24 or 26 (depending on the kernel version
used).
Code Listing 6.3: Getting the binary policy version |
# sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 24
Policy from config file: strict
|
Every time functionalities or capabilities are added which require
changes to the internal structure of the compiled policy, this version is
incremented. The following is an overview of the policy versions' history,
basically translated from the security/selinux/include/security.h
file in the Linux kernel.
- Version 12
- "Old API" for SELinux, which is now deprecated
- Version 15
- "New API" for SELinux, merged in Linux kernel 2.6.0 (until 2.6.5)
- Version 16
- Conditional policy extensions added (2.6.5)
- Version 17
- IPV6 support added (2.6.6 - 2.6.7)
- Version 18
- Fine-grained netlink socket support added (2.6.8 - 2.6.11)
- Version 19
- Enhanced multi-level security (2.6.12 - 2.6.13)
- Version 20
- Access vector table size optimizations (2.6.14 - 2.6.18)
- Version 21
- Object classes in range transitions (2.6.19 - 2.6.24)
- Version 22
- Policy capabilities (features) (2.6.25)
- Version 23
- Per-domain permissive mode (2.6.26 - 2.6.27)
- Version 24
- Explicit hierarchy (type bounds) (2.6.28 - 2.6.38)
- Version 25
- Filename based transition support (2.6.39)
- Version 26
- Role transition support for non-process classes (3.0)
- Version 27
- Support flexible inheritance of user and role for newly created objects (3.5)
- Version 28
- Support flexible inheritance of type for newly created objects (3.5)
2.g. Next Steps
What Next
It might be difficult to understand now, but the concepts are important because,
if something fails on your system when SELinux is enabled, but it doesn't fail
when SELinux is disabled, then you will need to dive into the security contexts,
rules, types and domain transitions to find out why.
The next chapter in line will give you some background resource information
(online resources, books, FAQs, etc.) After that, we'll dive into the
installation and configuration of SELinux on your Gentoo Hardened system. Then,
we'll configure and tune the SELinux policy to our needs.
3. SELinux Resources
3.a. Background
Introduction to SELinux
3.b. SELinux Policy
Policy Related References
3.c. Books
Paper Books
-
SELinux by Example: Using Security Enhanced Linux, Frank Mayer,
Karl MacMillan, and David Caplan, Prentice Hall, 2006; ISBN 0131963694
-
SELinux: NSA's Open Source Security Enhanced Linux, Bill McCarty,
O'Reilly Media, 2004; ISBN 0596007167
3.d. Gentoo Specific Resources
Gentoo Hardened
The following resources are specific towards Gentoo Hardened's SELinux
implementation.
B. Using Gentoo/Hardened SELinux
1. Gentoo SELinux Installation / Conversion
1.a. Installing Gentoo (Hardened)
Introduction
Getting a SELinux-powered Gentoo installation doesn't require weird actions.
What you need to do is install Gentoo Linux with the correct profile, correct
kernel configuration and some file system relabelling. We seriously recommend to
use SELinux together with other hardening improvements (such as PaX /
grSecurity).
This chapter will describe the steps to install Gentoo with SELinux. We
assume that you have an existing Gentoo Linux system which you want to convert
to Gentoo with SELinux. If this is not the case, you should still read
on: you can install Gentoo with SELinux immediately if you make the
correct decisions during the installation process, based on the information in
this chapter.
Performing a Standard Installation
Install Gentoo Linux according to the Gentoo
Handbook installation instructions. We recommend the use of the hardened
stage 3 tarballs and hardened-sources kernel instead of the standard
ones, but standard stage installations are also supported for SELinux.
Perform a full installation to the point that you have booted your system
into a (primitive) Gentoo base installation.
Note:
If you are an XFS user, make sure that the inode sizes of the XFS file
system is 512 byte. Since the default is 256, you will need to run the
mkfs.xfs command with the -i size=512 arguments, like so:
mkfs.xfs -i size=512 /dev/sda3
|
Switching to Python 2
For now, the SELinux management utilities are not all compatible with Python 3 so
we recommend to switch to Python 2 until the packages are updated and fixed.
Code Listing 1.1: Switching to python 2 |
~# emerge '<=dev-lang/python-3.0'
~# eselect python list
Available Python interpreters:
[1] python2.7
[2] python3.1 *
~# eselect python set 1
~# source /etc/profile
|
Choosing a SELinux policy type
Gentoo supports four policy types within SELinux: strict,
targeted, mcs and mls.
The differentiation between strict and targeted is based upon the
unconfined domain. When loaded, the processes on your system that are not
specifically confined within a particular policy module will be part of the
unconfined domains whose purpose is to allow most activities by default (rather
than deny by default). As a result, processes that run inside unconfined
domains have no restrictions apart from those already enforced by standard Linux
security. Although running without the unconfined domains is considered more
secure, it will also be more challenging for the administrator to make sure the
system still functions properly as there are no policy modules for each and
every application "out there".
Next to targeted and strict, you can opt for mcs to allow
categorization of the process domains. This is useful on multi-tenant systems
such as web servers, virtualization hosts, ... where multiple processes will be
running, most of them in the same security domain, but in different categories.
Note though that to take advantage of the additional category support, either
the applications themselves (such as the web server or hypervisor tools) need to
configure the SELinux categories (so they need to support SELinux) or you will
need to script around to start the individual instances with separate
categories. Otherwise, mcs is just the same as targeted or
strict.
Finally, you can also select mls to differentiate security domains on
a sensitivity level. However, MLS is currently still considered experimental
in Gentoo and as such not recommended.
In case of mcs or mls, you will need to use the unconfined
USE flag to enable or disable unconfined domains in these policy types. The
strict (no unconfined domains) type does not honor the USE flag, and the
targeted (unconfined domains) type requires the USE flag set.
When you have made your choice between the SELinux policy types, save
this in your /etc/make.conf file as well. That way, Portage will
only install the policy modules for that SELinux type. By default, the SELinux
profiles enable strict and targeted (with strict being the
default active type).
Code Listing 1.2: Setting the policy type in make.conf |
~# nano /etc/make.conf
POLICY_TYPES="strict"
|
Setting the filesystem contexts
If your /tmp location is a tmpfs-mounted file system, then you need
to tell the kernel that the root context of this location is tmp_t
instead of tmpfs_t. Many SELinux policy objects (including various
server-level policies) assume that /tmp is tmp_t.
To configure the /tmp mount, edit your /etc/fstab:
Code Listing 1.3: Update /etc/fstab for /tmp |
tmpfs /tmp tmpfs defaults,noexec,nosuid,rootcontext=system_u:object_r:tmp_t 0 0
tmpfs /tmp tmpfs defaults,noexec,nosuid,rootcontext=system_u:object_r:tmp_t:s0 0 0
|
Next, set the next line in your /etc/fstab to configure the context
for the /run location:
Code Listing 1.4: Update /etc/fstab for /run |
tmpfs /run tmpfs mode=0755,nosuid,nodev,rootcontext=system_u:object_r:var_run_t 0 0
tmpfs /run tmpfs mode=0755,nosuid,nodev,rootcontext=system_u:object_r:var_run_t:s0 0 0
|
Change the Gentoo Profile
Now that you have a running Gentoo Linux installation, switch the Gentoo profile
to the right SELinux profile (for instance,
hardened/linux/amd64/no-multilib/selinux). Note that the older
profiles (like selinux/v2refpolicy/amd64/hardened) are not
supported anymore.
Code Listing 1.5: Switching the Gentoo profile |
~# eselect profile list
Available profile symlink targets:
[1] default/linux/amd64/10.0
[2] default/linux/amd64/10.0/selinux
[3] default/linux/amd64/10.0/desktop
[4] default/linux/amd64/10.0/desktop/gnome
[5] default/linux/amd64/10.0/desktop/kde
[6] default/linux/amd64/10.0/developer
[7] default/linux/amd64/10.0/no-multilib
[8] default/linux/amd64/10.0/server
[9] hardened/linux/amd64
[10] hardened/linux/amd64/selinux
[11] hardened/linux/amd64/no-multilib *
[12] hardened/linux/amd64/no-multilib/selinux
~# eselect profile set 12
|
Note:
Starting from the profile change, Portage will warn you after every installation
that it was "Unable to set SELinux security labels". This is to be expected,
because the tools and capabilities that Portage requires to set the security
labels aren't available yet. This warning will vanish the moment the SELinux
installation is completed.
|
Don't update your system yet - we will need to install a couple of packages in a
particular order which Portage isn't aware of in the next couple of sections.
Update make.conf
Next, take a look at the following USE flags and decide if you want to enable
or disable them.
| USE flag |
Default Value |
Description |
| peer_perms |
Enabled |
The peer_perms capability controls the SELinux policy network peer controls.
If set, the access control mechanisms that SELinux uses for network based
labelling are consolidated. This setting is recommended as the policy is
also updated to reflect this. If not set, the old mechanisms (NetLabel and
Labeled IPsec) are used side by side.
|
| open_perms |
Enabled |
The open_perms capability enables the SELinux permission "open" for files
and file-related classes. Support for the "open" call was added a bit later
than others so support was first made optional. However, the policies have
matured sufficiently to have the open permission set.
|
| ubac |
Enabled |
When disabled, the SELinux policy is built without user-based access control.
|
| unconfined |
Disabled |
When set, policy builds (except for the "strict" policy) will include the
unconfined module (thus allowing unconfined domains to exist on the system).
|
Make your choice and update the USE variable in
/etc/make.conf or in an appropriate
/etc/portage/package.use location for the
sec-policy/selinux-base package.
Manual System Changes
Warning:
Most, if not all of the next few changes will be resolved through regular
packages as soon as possible. However, these fixes have impact beyond the Gentoo
Hardened installations. As such, these changes will be incorporated a bit slower
than the SELinux-specific updates. For the time being, manually correcting these
situations is sufficient (and a one-time operation).
|
The following changes might be necessary on your system, depending on the
tools or configurations that apply.
-
Check if you have *.old files in /bin. If you do,
either remove those or make them a copy of their counterpart so that they
get their own security context. The .old files are hard links
which mess up the file labelling. For instance, cp /bin/hostname
/bin/hostname.old.
Installing a SELinux Kernel
Although the default Linux kernels offer SELinux support, we recommend the use
of the sys-kernel/hardened-sources package.
Code Listing 1.6: Installing hardened-sources |
~# emerge hardened-sources
|
Next, reconfigure the kernel with the appropriate security settings. This
includes, but is not limited to
- Support for extended attributes in the various file systems
- Support system-call auditing
- Support for SELinux
Below you can find a quick overview of the recommended settings.
Code Listing 1.7: Recommended settings for the Linux kernel configuration |
[*] Prompt for development and/or incomplete code/drivers
[*] Auditing support
[*] Enable system-call auditing support
<*> Second extended fs support
[*] Ext2 extended attributes
[ ] Ext2 POSIX Access Control Lists
[*] Ext2 Security Labels
[ ] Ext2 execute in place support
<*> Ext3 journalling file system support
[ ] Default to 'data=ordered' in ext3
[*] Ext3 extended attributes
[ ] Ext3 POSIX Access Control Lists
[*] Ext3 Security Labels
<*> The Extended 4 (ext4) filesystem
[*] Ext4 extended attributes
[ ] Ext4 POSIX Access Control Lists
[*] Ext4 Security Labels
<*> JFS filesystem support
[ ] JFS POSIX Access Control Lists
[*] JFS Security Labels
[ ] JFS debugging
[ ] JFS statistics
<*> XFS filesystem support
[ ] XFS Quota support
[ ] XFS POSIX ACL support
[ ] XFS Realtime subvolume support (EXPERIMENTAL)
[ ] XFS Debugging Support
<*> Btrfs filesystem (EXPERIMENTAL)
[ ] Btrfs POSIX Access Control Lists
[*] Enable different security models
[*] Socket and Networking Security Hooks
[*] NSA SELinux Support
[ ] NSA SELinux boot parameter
[ ] NSA SELinux runtime disable
[*] NSA SELinux Development Support
[ ] NSA SELinux AVC Statistics
(1) NSA SELinux checkreqprot default value
[ ] NSA SELinux maximum supported policy format version
Default security module (SELinux) --->
|
We recommend to use PaX as well. More information on PaX within Gentoo Hardened
can be found in the Hardened
Gentoo PaX Quickstart Guide.
Build and install the new Linux kernel and its modules.
Update fstab
Next, edit /etc/fstab and add the following line:
Code Listing 1.8: Enabling selinux-specific file system options |
none /selinux selinuxfs defaults 0 0
|
Also create this mount point
Code Listing 1.9: Creating the /selinux mountpoint |
# mkdir /selinux
|
Reboot
With the above changes made, reboot your system. Assert yourself that you are
now running a Linux kernel with SELinux enabled (the /selinux file
system should be mounted). Don't worry - SELinux is at this point not activated.
1.b. Configure SELinux
Introduction
Next we will need to configure SELinux by installing the appropriate
utilities, label our file system and configure the policy.
Install Policies and Utilities
First, install the sys-apps/checkpolicy and
sys-apps/policycoreutils packages. Although these will be pulled in
as dependencies of the SELinux policy packages themselves, we need to install
these one time first - hence the -1 option.
Code Listing 2.1: Installing SELinux policy core utilities |
~# emerge -1 checkpolicy policycoreutils
|
Next, install the SELinux policy package
(sec-policy/selinux-base-policy). This package contains the base
SELinux policy needed to get your system up and running using SELinux.
As Portage will try to label and reload policies (since the installation of
sys-apps/policycoreutils) we need to temporarily disable SELinux
support (as Portage wouldn't be able to label anything as it doesn't understand
it yet).
Code Listing 2.2: Installing the SELinux policy packages |
~# FEATURES="-selinux" emerge selinux-base-policy
|
Next, rebuild those packages affected by the profile change we did previously
through a standard world update, taking into account USE-flag changes (as the
new profile will change many default USE flags, including enabling the
selinux USE flag). Don't forget to use etc-update or
dispatch-conf afterwards as some changes to configuration files need to
be made.
Code Listing 2.3: Update your Gentoo Linux system |
~# emerge -uDN world
|
Next, install the additional SELinux tools that you might need in the future to
debug or help with your SELinux installation. These packages are optional, but
recommended.
Code Listing 2.4: Installing additional SELinux packages |
~# emerge setools sepolgen checkpolicy
|
Finally, install the policy modules for those utilities you think you need
policies for. In the near future, this will be done automatically for you (the
packages will have an optional dependency on it, triggered by the selinux USE
flag), but until that time, you will need to install them yourself.
Code Listing 2.5: Installing SELinux modules |
~# emerge --search selinux-
[...]
~# emerge selinux-screen selinux-gnupg selinux-sudo selinux-ntp selinux-networkmanager ...
|
Configure the SELinux Policy
Inside /etc/selinux/config you can configure how SELinux is
configured at boot time.
Code Listing 2.6: Editing the /etc/selinux/config file |
# This file controls the state of SELinux on the system on boot.
# SELINUX can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=permissive
# SELINUXTYPE can take one of these four values:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.
# mls - Full SELinux protection with Multi-Level Security
# mcs - Full SELinux protection with Multi-Category Security
# (mls, but only one sensitivity level)
SELINUXTYPE=strict
|
Within this configuration file, two variables can be set:
-
SELINUX sets how SELinux should behave:
-
enforcing will enable and enforce policies. This is where we want
to go for, but you should probably start with permissive.
-
permissive will enable policies, but not enforce them. Any
violation is reported but not denied. This is where you should start
from as it will not impact your system yet allow you to get acquainted
with SELinux - and validate the warnings to see if you can switch
towards enforcing or not.
-
disabled will completely disable the policies. As this will not
show any violations as well, it is not recommended.
-
SELINUXTYPE selects the SELinux policy type to load. Most development
is done using the strict (as it provides full confinement) type,
although the others are supported as well.
Reboot, and Label the File System
Important:
Repeat these steps every time you have rebooted from a non-SELinux enabled
kernel into a SELinux enabled kernel, as running with a non-SELinux enabled
kernel will not update the security attributes of the files you create or
manipulate during your day-to-day activities on your system.
|
First reboot your system so that the installed policies are loaded. Now we
need to relabel your devices and openrc related files. This will apply the
correct security contexts (labels) onto the necessary files.
Code Listing 2.7: Relabel /dev structure |
~# mkdir /mnt/gentoo
~# mount -o bind / /mnt/gentoo
~# setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/dev
~# setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/lib64
~# umount /mnt/gentoo
|
Next, if you have a swapfile rather than a swap partition, label it accordingly:
Code Listing 2.8: Labelling the swap file |
~# semanage fcontext -a -t swapfile_t "/swapfile"
~# restorecon /swapfile
|
Now relabel your entire file system. The next command will apply the correct
security context onto the files on your file system, based on the security
context information provided by the SELinux policy modules installed.
Code Listing 2.9: Relabel the entire file system |
~# rlpkg -a -r
|
If you ever have to install a SELinux policy module for a package after that
that particular package is installed, you need to run rlpkg for that
package to make sure that the security contexts for these files are set
correctly. For instance, if you have installed
sec-policy/selinux-screen after discovering that you have
screen on your system:
Code Listing 2.10: Relabeling the files for a single package |
~# rlpkg -t screen
|
Enable the selinux_gentoo service
Gentoo provides an init script called selinux_gentoo which restores
the contexts of dynamically created files and devices or pseudo file systems
(/dev (optionally) and /sys) as those file systems
cannot persist context changes across reboots.
The init script also supports booting in permissive mode first (for instance if
you have a custom initramfs that fails to work in enforcing mode) and switch to
enforcing mode later.
Enable the init script using rc-update add selinux_gentoo boot and update
your boot loader configuration with the following boot options:
-
nosetenforce if you boot with enforcing=0 and do not
want the init script to switch back to enforcing mode (if configured in
/etc/selinux/config). If your /etc/selinux/config
file is configured to boot in permissive mode, this init script will not
change this behavior.
-
norestorecon if you do not want to restore the contexts of
/dev.
Code Listing 2.11: Example GRUB configuration |
title Gentoo Hardened/SELinux
root (hd0,0)
kernel /boot/kernel root=/dev/vg/root ... enforcing=0 ...
title Gentoo Hardened/SELinux
root (hd0,0)
kernel /boot/kernel root=/dev/vg/root ... enforcing=0 nosetenforce ...
|
Reboot and Set SELinux Booleans
Reboot your system so that the newly applied file contexts are used. Log on
and, if you have indeed installed Gentoo using the hardened sources (as we
recommended), enable the SSP SELinux boolean, allowing every domain read
access to the /dev/urandom device:
Code Listing 2.12: Enabling the global_ssp boolean |
~# setsebool -P global_ssp on
|
Define the Administrator Accounts
If the SELINUXTYPE is set to strict, then we
need to map the account(s) you use to manage your system (those
that need access to Portage) to the staff_u SELinux user. If not, none
of your accounts will be able to succesfully manage the system (except for
root, but then you will need to login as root directly and not
through sudo or su.) By default, users are mapped to the
user_u SELinux user who doesn't have the appropriate rights (nor access
to the appropriate roles) to manage a system. Accounts that are mapped to
staff_u can, but might need to switch roles from staff_r to
sysadm_r before they are granted the appropriate privileges.
Assuming that your account name is john:
Code Listing 2.13: Mapping the Linux account john to the SELinux user staff_u |
~# semanage login -a -s staff_u john
~# restorecon -R -F /home/john
|
If you later log on as john and want to manage your system, you will
probably need to switch your role. You can use newrole for this:
Code Listing 2.14: Switching roles |
~$ id -Z
staff_u:staff_r:staff_t
~$ newrole -r sysadm_r
Password:
~$ id -Z
staff_u:sysadm_r:sysadm_t
|
If you however use a targeted policy, then the user you work with will be
of type unconfined_t and will already have the necessary privileges to
perform system administrative tasks.
With that done, enjoy - your first steps into the SELinux world are now made.
Supporting Service Administration
By default, the Gentoo Hardened SELinux policies will allow the sysadm_t domain
access to all services. However, some of these services have policies that allow
them to be assigned to individual, non-root users. This requires the user to be
granted the system_r role (meaning the user can, under certain
circumstances, have his role change towards the system role).
It is therefor recommended to grant the system_r role to the
administrative SELinux user you are going to use most. This most likely is the
root and staff_u SELinux user.
Code Listing 2.15: Granting the system_r role to the staff and root user |
# semanage user -a -R "staff_r sysadm_r system_r" root
# semanage user -a -R "staff_r sysadm_r system_r" staff_u
|
2. Configuring SELinux For Your Needs
2.a. Administering Users
Introduction
During the installation, we already covered how to map a Linux user to a SELinux
user. In the example, we used a hypothetical user "john" and mapped him to the
SELinux user "staff_u". If you are running a multi-user system, managing the
right mappings is important. A user that is mapped to the SELinux user "user_u"
will not get any additional rights. Even if you would give that user additional
rights through commands such as sudo, the SELinux policy will not allow
this user to do anything that is administration related.
For this reason, it is important to go over the SELinux user mappings and the
Linux users on your system.
User Mappings
Run semanage login -l to show the current mappings between Linux logins
and SELinux users.
Code Listing 1.1: Running semanage login -l |
# semanage login -l
Login Name SELinux User
__default__ user_u
root root
john staff_u
system_u system_u
|
The "user_u" SELinux user is for regular accounts. As such, the special
__default__ mapping is defined by SELinux to denote every login that is
not defined otherwise. This makes sure that a newly defined account does not get
elevated privileges by default.
The next table gives an overview of the standard SELinux users available after
an installation.
| SELinux User |
Description |
| user_u |
Default regular SELinux user, which should be used by end-user accounts that
are not going to administer any service(s) on the system
|
| staff_u |
SELinux user for administrators. This user has the right to switch roles and
as such gain elevated privileges
|
| root |
SELinux user for the root account. It differs little from the staff_u
account beyond being a different ID. This ensures that files protected by
the user based access control for root cannot be handled by the staff_u
(and other) users
|
| sysadm_u |
SELinux user for system administration. By default, this account is not
immediately used as this user immediately gets the administrative role
(whereas staff_u and root still need to switch roles).
|
| system_u |
SELinux user for system services. It should never be used for end users or
administrators as it provides direct access to the system role (and
privileges)
|
| unconfined_u |
Used when the policy is targeted, this SELinux user has many
privileges (it is essentially not limited in its actions, although it is
still handled through SELinux - just through a "wide open" policy).
|
To map a user to a specific SELinux user, use semanage login -a:
Code Listing 1.2: Mapping a user 'sophie' to the staff_u user |
# semanage login -a -s staff_u sophie
|
However, when you update such mapping, the files in that users' home directory
will be owned by a wrong SELinux user. It is therefor important to relabel the
files of that user:
Code Listing 1.3: Relabeling sophie's files |
# restorecon -R -F /home/sophie
|
Additional SELinux Accounts
It is perfectly possible to create additional SELinux accounts, and then map the
Linux logins to these new accounts. This can be necessary when you want a more
thorough auditing (on end user level) or when you will be enhancing the policy
with additional roles. Also, if you want to use the User Based Access Control
feature, using different SELinux users is important to enforce the control on
different users (if they all use the same SELinux user, then UBAC has little to
no effect).
Managing the SELinux accounts is done through semanage user:
Code Listing 1.4: Creating a SELinux user |
# semanage user -a -R "staff_r sysadm_r" sophie
|
Let's verify how the SELinux users are currently configured:
Code Listing 1.5: Checking the SELinux user identities |
# semanage user -l
SELinux User SELinux Roles
root staff_r sysadm_r
sophie staff_r sysadm_r
staff_u staff_r sysadm_r
sysadm_u sysadm_r
system_u system_r
unconfined_u unconfined_r
user_u user_r
# semanage login -l
Login Name SELinux User
__default__ user_u
root root
sophie staff_u
swift staff_u
system_u system_u
|
Now that a new SELinux user called "sophie" exists, we can now update the Linux
user mapping for "sophie" towards the new SELinux user "sophie":
Code Listing 1.6: Updating the Linux user mapping |
# semanage login -m -s sophie sophie
# semanage login -l
Login Name SELinux User
__default__ user_u
root root
sophie sophie
swift staff_u
system_u system_u
|
Again, do not forget to relabel this users' files.
As you can see, managing SELinux users means defining the roles to which the
user has access to. We already gave a high-level introduction to the default
roles in SELinux Concepts, but as roles are
important when using a Mandatory Access Control system, let's refresh our memory
again:
| SELinux Role |
Description |
| user_r |
Default end-user role. This role provides access to regular applications and
activities, but does not allow any system or service administration beyond
what is expected for a regular user.
|
| staff_r |
Default administration role for day-to-day activities. This role has some
additional privileges beyond what is offered through user_r, but is not a
full system administrative role. It is meant for the non-administrative
activities done by operators and administrators
|
| sysadm_r |
System administration role. This role is highly privileged (since it also
contains the privileges to update the policy) and should only be given to
fully trusted administrators. It is almost never immediately granted to
users (they first need to switch roles) except for direct root access (for
instance through the console)
|
| system_r |
System service role, which is used for the runtime services (processes). It
is only granted to users when they get specific, limited administrative
rights (for instance administration rights on a single daemon domain).
|
| unconfined_r |
The unconfined role is used when the targeted policy is supported.
This role is given to unconfined users (such as the SELinux unconfined_u
user) which have very wide privileges (they almost run without constraints).
|
It should be noted that these roles are the default ones, but the security
administrator - yes, that means you - can create additional roles and add
particular privileges to it. We will discuss this later in this book as it means
you'll need to update the Gentoo Hardened SELinux policy.
2.b. Reading Audit Logs
Introduction
When working with a SELinux-enabled system, you will eventually notice that
things behave differently, but without giving any meaningful error message.
Usually, when SELinux "denies" a particular access, it logs it into the audit
log of the system, but for the application itself, it is perfectly possible that
it just silently dies. If not, you're most likely to get a permission
denied error message.
Initially, SELinux is running in permissive mode, which means that
SELinux will log what it would deny, but still let it through.
This mode is perfect for getting the system in shape without having too
much problems keeping it running. Once you think your security settings are
in order, then this mode can be switched from permissive to
enforcing. We'll talk about these modes later.
First, let's take a look at the audit log and see what it is saying...
Audit Log Location(s)
The SELinux kernel code writes its denials (and sometimes even allowed but
audited activities) into the audit log. If you are running on a Gentoo Hardened
installation with the syslog-ng system logger, then the logger is already
configured to place these audit lines in /var/log/avc.log. However,
different system loggers or system logger configurations might put the entries
in a different log location (such as /var/log/audit.log).
Below, you'll find the appropriate lines for the syslog-ng system logger
configuration for writing the events in /var/log/avc.log.
Code Listing 2.1: syslog-ng.conf excerpt for SELinux AVC entries |
source kernsrc { file("/proc/kmsg"); };
destination avc { file("/var/log/avc.log"); };
filter f_avc { message(".*avc: .*"); };
log {
source(kernsrc);
filter(f_avc);
destination(avc);
};
|
What is AVC?
As we mentioned, SELinux writes its entries in the audit log. These entries are
called avc messages or avc log entries. The abbreviation AVC
stands for Access Vector Cache and, like the name sais, is a caching
system.
Using an access vector cache improves performance on dealing with (and
enforcing) activities and privileges. Since SELinux offers a very detailed
approach on privileges and permissions, it would become quite painful
(performance-wise) if each call means that the SELinux code needs to look up the
domain, the target resource label, the privilege and if it is allowed or not
over and over again. Instead, SELinux uses the Access Vector Cache to store past
requests/responses. It is the AVC subsystem that is responsible for checking
accesses and (if necessary) logging it.
Reading an AVC Denial Message
Below you'll find a typical AVC denial message.
Code Listing 2.2: Example AVC denial message |
Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
avc: denied { module_request } for pid=14561 comm="firefox" kmod="net-pf-10"
scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system
|
Let's analyze each part of this message one by one.
Code Listing 2.3: AVC denial: Timestamp and location information |
Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
avc: denied { module_request } for pid=14561 comm="firefox" kmod="net-pf-10"
scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system
|
This first part of the message informs you when the message was written (Oct 15
13:04:54), on which host (hpl) and how many seconds since the system was booted
(963185.177043).
Code Listing 2.4: AVC denial: source information |
Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
avc: denied { module_request } for pid=14561 comm="firefox" kmod="net-pf-10"
scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system
|
Next is the source of the denial, i.e. what process is trying to do something.
In this case, the process is firefox, with PID 14561, which is running in the
source domain staff_u:staff_r:mozilla_t.
Code Listing 2.5: AVC denial: target resource |
Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
avc: denied { module_request } for pid=14561 comm="firefox" kmod="net-pf-10"
scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system
|
The target of the activity is a kernel module (net-pf-10, which is the internal
name given for IPv6), labeled system_u:system_r:kernel_t
Code Listing 2.6: AVC denial: denied action |
Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
avc: denied { module_request } for pid=14561 comm="firefox" kmod="net-pf-10"
scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system
|
Finally, the action that is denied (module_request) and its class (system).
These classes help you to identify what is denied, because a read on a file is
different from a read on a directory.
For instance, in the following case, a process gorg with PID 13935 is
trying to read a file called localtime with inode 130867 which
resides on the device /dev/md3:
Code Listing 2.7: AVC denial example |
Oct 15 14:40:30 hpl kernel: [968909.807802] type=1400 audit(1318682430.323:2614):
avc: denied { read } for pid=13935 comm="gorg" name="localtime" dev=md3 ino=130867
scontext=staff_u:sysadm_r:gorg_t tcontext=system_u:object_r:locale_t tclass=file
|
In this case, it might be obvious that the file is /etc/localtime,
but when that isn't the case, then you can find the following two commands
useful:
Code Listing 2.8: Finding out the target resource based on inode and device |
# mount | grep /dev/md3
/dev/md3 on / type ext4 (rw,seclabel,noatime,barrier=1,nodelalloc,data=journal)
# find / -xdev -inum 130867
/etc/localtime
|
Handling AVC denials
The major part of configuring SELinux is reading the denials, finding out what
needs to be fixed (or ignored), fix it, and repeat the steps. Hopefully, the
rest of this handbook will help you figure out what is causing a denial.
Denials can be cosmetic (an activity that is denied, but has no effect on the
application's functional behaviour). If that is the case, the denial can be
marked as dontaudit, meaning that the denial is not logged by default
anymore. If you think that a denial is occurring but you do not see it in the
logs, try disabling the dontaudit rules:
Code Listing 2.9: Disabling dontaudit |
# semodule --build --disable_dontaudit
|
In most cases though, denials need to be acted upon. Actions that might need to
happen are:
-
relabeling the target resource (wrong labels might cause legitimate actions
to be denied)
-
relabeling the source (process' binary file) as a wrong label might cause
the application to run in the wrong domain
-
loading a necessary SELinux module, since the modules contain the rules to
allow (and label) resources. Without the appropriate module loaded, you will
notice denials since no other module gives the necessary grants (allow
statements)
-
granting the right role to the user executing the application. We have
covered users and their roles initially but we will go deeper into this
subject later in the handbook.
-
adding your own SELinux policy statements, most likely because no SELinux
policy module exists for the application you are trying to run
2.c. Using (File) Labels
Introduction
Within SELinux, access privileges are based on the label given on the
originating part (called the domain) and its target resource. For
instance, a process running in the passwd_t domain wants to read (= privilege)
the file /etc/shadow which is labeled shadow_t (= the target
resource). It comes to no surprise then that the majority of SELinux
administration is (re)labeling the resources correctly (and ensuring their label
stays correct).
Getting File Label(s)
There are many ways to relabel commands, and none of them are equal to another.
But before we explain this in more detail, let's first take a look at a few file
labels (and how you can query them).
In SELinux, labels are given on a file level through the file systems' ability
to keep extended attributes. For SELinux, the attribute is called
security.selinux and can be obtained through getfattr:
Code Listing 3.1: Getting a file's extended attribute for SELinux |
$ getfattr -n security.selinux /etc/hosts
# file: etc/hosts
security.selinux="system_u:object_r:net_conf_t"
|
Of course, getting the file attribute this way is time consuming and not that
flexible. For this purpose, most important applications (including
coreutils) are made SELinux-aware. These applications mostly use the
-Z option to display the SELinux context information. In case of files,
this means the extended attribute content:
Code Listing 3.2: Getting the context of a file |
$ ls -Z /etc/hosts
system_u:object_r:net_conf_t /etc/hosts
|
Other commands exist that display the context as it should be, like
matchpathcon. However, their purpose is to query the SELinux policy on
your system to find out what the policy ought to be, not what it is:
Code Listing 3.3: Difference between context and matchpathcon result |
$ ls -Z /etc/make.conf
staff_u:object_r:etc_t /etc/make.conf
$ matchpathcon /etc/make.conf
/etc/make.conf system_u:object_r:portage_conf_t
|
Setting File Label(s)
Now how can you manipulate file labels? Well, first of all: you will not be
allowed to change the file labels of any possible file (not even if you are the
owner of that file) unless the SELinux policy allows you to. These allow rules
are made on two privilege types: which labels are you allowed to change
(relabelfrom) and to which labels are you allowed to change
(relabelto). You can query these rules through sesearch:
Code Listing 3.4: Querying the relabelto/relabelfrom types |
$ sesearch -s user_t -c file -p relabelfrom -A
allow user_t mozilla_home_t : file { relabelfrom relabelto } ;
|
If you have the permission, then you can use chcon to change the
context of a file:
Code Listing 3.5: Changing a file context |
$ ls -Z strace.log
staff_u:object_r:user_home_t strace.log
$ chcon -t mutt_home_t strace.log
$ ls -Z strace.log
staff_u:object_r:mutt_home_t strace.log
|
If you do not hold the right privileges, you will get a descriptive error
message:
Code Listing 3.6: Trying to change file context |
$ chcon -t shadow_t strace.log
chcon: failed to change context of `strace.log' to `staff_u:object_r:shadow_t': Permission denied
|
Now, if you now think that chcon is all you need, you're wrong. The
chcon command does nothing more than what it sais - change context. But
when the system relabels files, these changes are gone. Relabeling files is
often done to ensure that the file labels are correct (as in: the labels match
what the SELinux policy sais they ought to be). The SELinux policy contains, for
each policy module, the list of files, directories, sockets, ... and their
appropriate file context (label).
We will look at SELinux policy modules later, but below you'll find an excerpt
from such a definition, for the mozilla module:
Code Listing 3.7: Excerpt of the mozilla module file contexts |
/usr/bin/firefox-bin -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/bin/mozilla-[0-9].* -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/bin/mozilla-bin-[0-9].* -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/lib(64)?/galeon/galeon -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/lib(64)?/netscape/.+/communicator/communicator-smotif\.real -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/lib(64)?/netscape/base-4/wrapper -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/lib/[^/]*firefox[^/]*/plugin-container -- gen_context(system_u:object_r:mozilla_plugin_exec_t,s0)
/usr/lib64/[^/]*firefox[^/]*/plugin-container -- gen_context(system_u:object_r:mozilla_plugin_exec_t,s0)
|
To put the right label on a file, you can use the setfiles or
restorecon commands. Since they are both the same command (but with a
slightly different way of using) we'll only talk about restorecon for now
- more information on the setfiles command can be found in its man page.
When you use restorecon, the application will query the SELinux policy to
find out what the right label of the file should be. If it differs, it will
change the label to the right setting. That means that you do not need to
provide the label for a file in order for the command to work. Also,
restorecon supports recursivity, so you do not need to relabel files one
by one.
Code Listing 3.8: Using restorecon |
$ ls -Z /etc/make.conf
staff_u:object_r:etc_t /etc/make.conf
$ restorecon /etc/make.conf
$ ls -Z /etc/make.conf
system_u:object_r:portage_conf_t /etc/make.conf
|
Finally, Gentoo also provides a useful application: rlpkg. This script
relabels the files of a Gentoo package (rlpkg <packagename>) or,
given the right arguments, all files on the file system:
Code Listing 3.9: Using rlpkg |
# rlpkg firefox
# rlpkg -a -r
|
Overriding the SELinux Policy File Labels
You might not always agree with the label that the SELinux policy enforces on
the files: you might have your files located elsewhere (a different location for
your Portage tree is a nice example) or you need to label them differently in
order for other applications to work. To not have to chcon these files
over and over again, you can enhance the SELinux policy on your system with
additional file context rules. These rules are used when you call
restorecon as well and override the rules provided by the SELinux policy.
To add additional file context rules, you need to use the semanage
command. This command is used to manage, manipulate and update the local SELinux
policy on your system. In this particular case, we will use the semanage
fcontext command:
Code Listing 3.10: Using semanage to add a file context rule |
# semanage fcontext -a -t portage_conf_t /mnt/gentoo/etc/make.conf
# semanage fcontext -a -t portage_ebuild_t "/mnt/gentoo/usr/portage(/.*)?"
|
As you can see from the example, you can use wildcards. But beware about using
wildcards: when a rule holds a wildcard, it has a lower priority than a rule
without a wildcard. And the priority on rules with a wildcard is based on how
"down" the string the first occurance of a wildcard is. For more information,
please check out our FAQ on "How do
I know which file context rule is used for a particular file?."
If you want to delete a file context definition, you use semanage fcontext
-d:
Code Listing 3.11: Deleting a file context definition |
# semanage fcontext -d -t portage_ebuild_t /mnt/gentoo/etc/make.conf
|
Finally, to view all file context definitions (both user-set and SELinux policy
provided), you can use semanage fcontext -l. To only see the locally set,
add -C:
Code Listing 3.12: Viewing user-set file context enhancements |
# semanage fcontext -C -l
SELinux fcontext type Context
/opt/xxe/bin/.*\.jar all files system_u:object_r:lib_t
/srv/virt/gentoo(/.*)? all files system_u:object_r:qemu_image_t
|
Customizable types
Labels on files are not that hard to understand, but you might come into some
surprises if you do not know that there are also customizable types.
A customizable type is a specific type which is not touched by the
SELinux administration tools by default. If you want to relabel a file that
currently holds a customizable type, you will need to force this through the
commands (such as restorecon -F).
There are not that many customizable types by default. The list of types that
SELinux considers as customizable are mentioned in the
customizable_types file within the
/etc/selinux/*/contexts location:
Code Listing 3.13: Listing the customizable types |
# cat /etc/selinux/strict/contexts/customizable_types
mount_loopback_t
public_content_rw_t
public_content_t
swapfile_t
textrel_shlib_t
|
Such types exist because these types are used for files whose location is known
not to be fixed (and as such, the SELinux policy cannot without a doubt know if
the label on the files is correct or not). The public_content_t one,
which is used for files that are readable by several services (like FTP, web
server, ...), might give you a nice example for such a case.
If you look at the restorecon man page, it mentions both customizable
types as well as the user section. The latter is for rules that are identified
in the SELinux policy as being files for an end user, like the following
definitions in the mozilla policy module:
Code Listing 3.14: User section definition within mozilla module |
HOME_DIR/\.mozilla(/.*)? gen_context(system_u:object_r:mozilla_home_t,s0)
HOME_DIR/\.netscape(/.*)? gen_context(system_u:object_r:mozilla_home_t,s0)
HOME_DIR/\.phoenix(/.*)? gen_context(system_u:object_r:mozilla_home_t,s0)
|
Although in the above example, forcing restorecon on the files is
probably correct, there are examples where you do not want this. For instance,
the firefox policy by default only allows the application to write to
directories labeled mozilla_home_t. If you want to download something,
this isn't possible (unless you download it into ~/.mozilla). The
solution there is to label a directory (say ~/Downloads) as
mozilla_home_t.
2.d. SELinux Policy and Booleans
Introduction
We have dealt with users and labels now, but there is still a third aspect that
we haven't touched: the SELinux policy itself.
The SELinux policy as offered by Gentoo Hardened is a carefully tuned SELinux
policy, based on the reference policy (a distribution-agnostic SELinux policy)
with minor changes. Hopefully, you will not need to rewrite the policy to suit
it for your needs, but changes are very likely to occur here and there.
Changing the SELinux Policy Behavior: Booleans
A common and user friendly way of tweaking the SELinux policy is through
booleans. A SELinux boolean, also known as a conditional, changes how the
SELinux policy behaves based on the setting that the user provides. To make this
a bit more clear, let's look at a few booleans available:
Code Listing 4.1: Getting SELinux booleans |
# getsebool -a | grep ^user
user_direct_mouse --> off
user_dmesg --> off
user_ping --> on
user_rw_noexattrfile --> off
user_tcp_server --> off
user_ttyfile_stat --> off
|
Although they might not say much on first sight, these booleans alter how the
SELinux policy enforces user activity (hence the booleans starting with
user_). For instance, user_ping is set to on, so a
user is allowed to use ping. If it was set to off, the SELinux
policy would not allow a user to execute ping.
Booleans can be toggled on or off using setsebool or togglesebool.
With setsebool you need to give the value (on or off) whereas
togglesebool switches the value.
Code Listing 4.2: Disallowing the use of ping by users |
# setsebool user_ping off
|
By default, setsebool does not store the boolean values - after a reboot,
the old values are used again. To persist such changes, you need to add the
-P option:
Code Listing 4.3: Persistedly allow users to run dmesg |
# setsebool -P user_dmesg on
|
Booleans allow administrators to tune the policy, and allow security
administrators to write policies that are flexible enough for a more widespread
use. In terms of Gentoo flexibility, these booleans might not be used enough (it
would be nice to couple these booleans on USE flags, so that a server build with
USE="ldap" gets the SELinux policy to use ldap, whereas USE="-ldap" disallows
it). But still, the use of booleans is a popular method for making a more
flexible SELinux policy.
Managing SELinux Policy Modules
In this last part, we'll cover SELinux policy modules. We mentioned before that
the SELinux policy used by Gentoo Hardened is based on the reference policy,
which offers a modular approach to SELinux policies. There is one base policy,
which is mandatory on every system and is kept as small as possible. The rest
are SELinux policy modules, usually providing the declarations, rules and file
contexts for a single application (or type of applications).
With semodule -l you can see the list of SELinux policy modules loaded:
Code Listing 4.4: Listing the loaded SELinux modules |
# semodule -l
alsa 1.11.0
apache 2.3.0
entropyd 1.6.0
dbus 1.15.0
dnsmasq 1.9.0
|
Within Gentoo Hardened, each module is provided by the package
sec-policy/selinux-<modulename>. For instance, the first
module encountered in the above example is provided by
selinux-alsa:
Code Listing 4.5: The SELinux policy module package in Gentoo |
$ emerge --search selinux-alsa
Searching...
[ Results for search key : selinux-alsa ]
[ Applications found : 1]
* sec-policy/selinux-alsa
Latest version available: 2.20110726
Latest version installed: 2.20110726
Size of files: 574 kB
Homepage: http://www.gentoo.org/proj/en/hardened/selinux/
Description: SELinux policy for alsa
License: GPL-2
|
If you need a module that isn't installed on your system, this is considered a
bug (packages that need it should depend on the SELinux policy package if the
selinux USE flag is set). But once you install the package yourself, the module
will be loaded automatically:
Code Listing 4.6: Installing a SELinux policy package |
# emerge selinux-screen
|
If you want to remove a module from your system though, uninstalling the package
will not suffice: the SELinux policy module itself is copied to the policy store
earlier (as part of the installation process) and is not removed from this store
by Portage. Instead, you will need to remove the module manually:
Code Listing 4.7: Uninstalling a SELinux policy module |
# emerge -C selinux-screen
# semodule -r screen
|
2.e. Next steps
What to do now?
Up until now, your system has been running in permissive mode. You will
need to enable enforcing before you are properly protected by SELinux. We
will discuss how to switch to enforcing mode in Permissive, Unconfined, Disabled or What Not...
but before that, you will need to consider a few things...
Initramfs users
If your system uses an initramfs to boot up, you will not be able to boot
straight into enforcing mode (due to bug #397597). To work around this
issue, you can create the following init script which will switch from a
permissive mode into forcing mode reasonably fast within the boot process (and
before the network is started):
Code Listing 5.1: Content of /etc/init.d/selinux_enforce |
#!/sbin/runscript
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo/xml/htdocs/proj/en/hardened/selinux/hb-using-configuring.xml,v 1.6 2012/12/29 18:19:39 swift Exp $
description="Switch into SELinux enforcing mode"
depend() {
need sysfs
}
start() {
if get_bootparam "norestorecon" ; then
ewarn "Skipping restoring file contexts in /dev as requested"
else
ebegin "Restoring file contexts in /dev"
restorecon -R /dev
eend 0
fi
if get_bootparam "nosetenforce" ; then
ewarn "Skipping switching to enforcing mode as requested by kernel cmdline"
else
. /etc/selinux/config
CURRENTMODE=$(cat /sys/fs/selinux/enforce)
if [ "${SELINUX}" = "enforcing" ] && [ "${CURRENTMODE}" = "0" ];
then
ebegin "Switching to enforcing mode"
echo 1 > /sys/fs/selinux/enforce
eend $?
else
ewarn "Not switching to enforcing mode, or enforcing mode already enabled"
fi
fi
}
|
Add the init script to the boot runlevel, and edit your boot loader
configuration to always boot with enforcing=0 set. The init script will
update the file contexts in /dev and then, if your system is
configured to run in enforcing mode, switch to enforcing mode.
If you need to temporarily stay in permissive mode, you can add
nosetenforce as boot parameter (after enforcing=0) which will skip
the setenforce step).
Users of a graphical environment
If you boot into a graphical environment (using GDM, KDM or another graphical
login manager) you will need to update the PAM configuration file(s) of the
managers with the following:
Code Listing 5.2: Example update on LXDM PAM configuration file |
session required pam_loginuid.so
session optional pam_gnome_keyring.so auto_start
session optional pam_selinux.so
|
This will ensure that the security context in which you are logged on is set
correctly. We will update the packages that place those PAM files accordingly,
but it might take some time.
3. SELinux Commands
3.a. SELinux Information Commands
Introduction
You should currently have a SELinux enabled system (but running in permissive
mode, so it will not enforce its policy rules). So before we introduce you to
the world of SELinux and how you can add more rules to make sure your system
remains functional when you switch to enforcing mode, we first give a quick
overview of the various SELinux related commands.
We start off with state commands where you can get global information on SELinux
state (is it running in enforcing mode or not, versions etc.)
Getting SELinux Status
The first command we will talk about is sestatus.
Code Listing 1.1: Running sestatus |
# sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: permissive
Mode from config file: permissive
Policy version: 24
Policy from config file: strict
|
The output of this command shows you that SELinux is enabled and is currently in
the permissive mode. It also tells you that the system is configured to
run in strict mode - so no unconfined_t domain here.
The sestatus command also has an extended output if you run it with the
-v option. When this is done, the command returns the contexts of
important processes and files:
Code Listing 1.2: Running sestatus -v |
# sestatus -v
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 24
Policy from config file: strict
Process contexts:
Current context: staff_u:sysadm_r:sysadm_t
Init context: system_u:system_r:init_t
/sbin/agetty system_u:system_r:getty_t
/usr/sbin/sshd system_u:system_r:sshd_t
File contexts:
Controlling term: staff_u:object_r:user_devpts_t
/sbin/init system_u:object_r:init_exec_t
/sbin/agetty system_u:object_r:getty_exec_t
/bin/login system_u:object_r:login_exec_t
/sbin/rc system_u:object_r:rc_exec_t
/usr/sbin/sshd system_u:object_r:sshd_exec_t
/sbin/unix_chkpwd system_u:object_r:chkpwd_exec_t
/etc/passwd system_u:object_r:etc_t
/etc/shadow system_u:object_r:shadow_t
/bin/sh system_u:object_r:bin_t -> system_u:object_r:shell_exec_t
/bin/bash system_u:object_r:shell_exec_t
/usr/bin/newrole system_u:object_r:newrole_exec_t
/lib/libc.so.6 system_u:object_r:lib_t -> system_u:object_r:lib_t
/lib/ld-linux.so.2 system_u:object_r:lib_t -> system_u:object_r:ld_so_t
|
Another general SELinux status command is getenforce, which allows you to
quickly see if your SELinux is running in enforcing mode (SELinux policies are
enforced), permissive (SELinux policies are checked and logged, but not
enforced) or disabled (SELinux policy is not loaded and thus not checked).
Code Listing 1.3: Using the getenforce command |
# getenforce
Enforcing
|
Getting SELinux Object Information
Next on the table is the seinfo command. This command allows you to query
the running policy for all objects (types, roles, attributes, users, booleans
...) defined.
Common usages are:
-
checking if a specific domain is defined on your system (in case you're
wondering if you need to load an additional SELinux policy module or not)
-
checking which domains a particular role can be in (in case you're wondering
if your regular users are allowed by SELinux policies to even be
transitioned towards a specific domain)
-
checking which attributes are assigned to a specific domain (or vice versa,
which domains have a specific attribute set) as some SELinux policy rules
work on attributes rather than domains
As an example, we query if the crontab_t domain is known, if the user_r role can
use the contab_t domain and finally which domains have the cron_spool_type
attribute set.
Code Listing 1.4: Using seinfo |
# seinfo -tcrontab_t
crontab_t
# seinfo -ruser_r -x
user_r
Dominated Roles:
user_r
Types:
[...]
crontab_t
[...]
# seinfo -acron_spool_type -x
cron_spool_type
user_cron_spool_t
system_cron_spool_t
|
Querying SELinux Policy Rules
A command which you will often use is sesearch. This command allows you
to query the current policy allow rules and is a huge help when trying to find
out if something is allowed (or why something isn't allowed).
The sesearch command is most often used with a source domain (-s),
target domain (-t) or both, the class for which you want to query allow
rules for (file, dir, socket, process ...) and the privilege you want to query
for (read, write, open, transition, execute ...).
For instance, to find out which domains can write the files that have the
shadow_t domain:
Code Listing 1.5: Querying allow rules with sesearch |
# sesearch -t shadow_t -c file -p write -A
Found 8 semantic av rules:
[...]
allow portage_t shadow_t : file { ioctl read write ... };
allow useradd_t shadow_t : file { ioctl read write ... };
...
|
You will notice that there are sometimes results based on attributes rather than
domains:
Code Listing 1.6: Allow rule based on attribute |
allow portage_t file_type : file { ioctl read write ... };
|
In this case, the source domain (portage_t) is allowed to write to files whose
domain have the file_type attribute set. If you get the feeling of these things,
you'll wonder if the above rule is not a flagrant security issue as almost all
domains for files have the file_type set. Yes and no - if we take a look at
which domains have file write privileges to file_type domains, you'll notice
that this is only portage:
Code Listing 1.7: Querying domains with file-write privileges to file_type domains |
# sesearch -t file_type -c file -p write -A -d
Found 1 semantic av rules:
allow portage_t file_type : file { ioctl read write ... };
|
Note that we had one command without the -d option and one with. When
-d is given, the search will perform an exact search without resolving
the attributes. When -d is not given, it will resolve the attribute. In
the last command example, dropping -d would result in hundreds of allow
rules: for each domain that has file_type set, the search tries to find rules
that allow file-write access to that particular domain.
Another interesting functionality of the sesearch command is to show you
the rules that are applicable depending on the state of a boolean. If you want
to query on a particular boolean, use -b. If you want to see the logic
that the policy uses, use -C (and yes, both can be combined).
As an example, we'll check what we allow (or deny) when the global_ssp
boolean is set:
Code Listing 1.8: Checking the policy regarding the global_ssp boolean |
# sesearch -b global_ssp -A -C -d
Found 2 semantic av rules:
ET allow domain device_t : dir { getattr search open } ; [ global_ssp ]
ET allow domain urandom_device_t : chr_file { ioctl read getattr lock open } ; [ global_ssp ]
|
The prefix you see shows two letters, relating to two important definitions:
-
Is the rule currently Enabled or Disabled?
-
Does the boolean need to be set to True or False to enable the rule?
Getting Security Context Information
During administrative tasks, and especially when you are checking if a SELinux
denial could be made, it is important to find out what the security context is
for a particular resource. Luckily, Gentoo Hardened - if properly installed -
has already patched some tools to allow you to get this information using your
standard tools.
To get the security context of a file, use ls -Z:
Code Listing 1.9: Getting a file security context |
~$ ls -Z /etc/make.conf
system_u:object_r:portage_conf_t /etc/make.conf
|
To get the security context of a process, use ps -Z:
Code Listing 1.10: Getting a process security context |
# ps -Z $(pidof init)
LABEL PID TTY STAT TIME COMMAND
system_u:system_r:init_t 1 ? Ss 0:00 init [3]
|
To get the security context of the current user, use id -Z:
Code Listing 1.11: Getting a user security context |
~$ id -Z
staff_u:staff_r:staff_t
|
3.b. Managing SELinux
Introduction
Managing SELinux objects (booleans, users, ports, contexts ...) is most often
done using semanage. As this application offers the interface towards
various SELinux configurations, we dedicate an entire section on it, but will
also cover the commands that offer similar functionality (and are sometimes
easier to remember).
Booleans
We have already covered SELinux booleans earlier in this book as well as the
getsebool and setsebool commands. With semanage you can too
manage the booleans and, as an added bonus, listing the booleans will also show
the description of the boolean (even though there is still work to be done in
this area).
Code Listing 2.1: Listing the available SELinux booleans |
# semanage boolean -l
SELinux boolean Description
allow_ptrace -> off allow_ptrace
rsync_export_all_ro -> off rsync_export_all_ro
|
Note:
As you will notice, most descriptions are just the boolean name, but you will
find more and more booleans with a better description as you get acquainted with
- and install more - SELinux policy modules.
|
You can set a boolean with both setsebool and semanage:
Code Listing 2.2: Setting SELinux boolean values |
# semanage boolean -m --on -F user_dmesg
|
SELinux Users and Logins
SELinux users and logins are different from Unix accounts. SELinux logins allow
you to map a Unix account to a SELinux user:
Code Listing 2.3: Listing the SELinux logins |
# semanage login -l
Login Name SELinux User
__default__ user_u
root root
swift staff_u
system_u system_u
|
The default behavior is that users are logged on as the user_u SELinux
user. This SELinux user is a non-administrator user: it has no specific
privileges and should be used for every account that never requires elevated
privileges (so no su or sudo rights for anything).
The account you use to administer your system should be mapped to the
staff_u SELinux user (or its own user with the appropriate roles). This
can be accomplished as follows (example with the Unix account anna):
Code Listing 2.4: Letting 'anna' log on as 'staff_u' |
# semanage login -a -s staff_u anna
|
Important:
Make sure that whatever account you use to administer your system is mapped to
the staff_u user, or has the ability to switch to the sysadm_r
role. Portage only works from within the sysadm_r role.
|
As mentioned, SELinux users are configured to be able to join in on one or more
roles. To list the available roles, you can use semanage user -l:
Code Listing 2.5: Listing login / role mappings |
# semanage user -l
SELinux User SELinux Roles
root staff_r sysadm_r
staff_u staff_r sysadm_r
[...]
|
Managing Ports
Even network ports (like port 22 for SSH) are 'protected' by SELinux. To get an
overview of which domains are assigned to which ports (or port ranges) use
semanage port -l.
Code Listing 2.6: Listing SELinux managed ports |
# semanage port -l | grep '22$'
ssh_port_t tcp 22
|
3.c. Using SELinux
Introduction
Up until now we've covered getting SELinux related information as well as
managing SELinux settings. However, users on a SELinux hardened system will also
need to know a few things about working with SELinux, including (but not limited
to) roles and role transitions.
Switching Roles
As a type enforcement access control system, SELinux allows particular roles to
be within a set of domains. If you are using a role which is not allowed within
a particular domain, you will not be successful in using that domain and will be
denied the actions assigned to that domain.
If your standard users are all SELinux user_u users (with the only supported
role being user_r) then those users will never need to switch roles (nor are
they allowed to). But users that are staff_u (or other users that have multiple
roles) those users should be made clear how they switch between roles. We have
already covered how to map such users to the correct SELinux user (see SELinux Users and Logins).
The command that accomplishes switching roles is called newrole. It's
use is pretty straight forward.
Code Listing 3.1: Using newrole |
~$ newrole -r sysadm_r
Password:
|
When performing a role transition, SELinux will ask the user to re-authenticate
through its users' password.
4. Permissive, Unconfined, Disabled or What Not...
4.a. SELinux States
Introduction
When SELinux is available, it will generally be in one of three states on your
system: disabled, permissive or enforcing.
Disabled
When getenforce returns "Disabled", then SELinux is not running on your
system. Even though it might be built in your kernel, it is definitely disabled.
Your system will still run with regular discretionary access controls (the usual
permission rules for standard Linux environments) but the mandatory access
controls are not active.
When SELinux is disabled, it also means that files, directories, etc that are
modified or created will not get the proper SELinux context assigned to them.
When you later start your system with SELinux enabled (permissive or enforcing),
issues will arise since the SELinux subsystem will not know which label the
files have (it will default the label to one that is not accessible by most
domains).
The best way to go forward in such case is to boot in permissive mode and then
relabel the entire file system:
Code Listing 1.1: Relabeling the entire file system |
# rlpkg -a -r
|
Permissive
When SELinux is enabled in permissive mode (getenforce returns
"Permissive"), then SELinux is enabled and it has a policy loaded. Every access
a process makes is checked against the policy rules and, if an access is not
allowed, it will be logged (unless the denial is marked as dontaudit) but it
will not be prohibited.
The permissive mode is perfect to get acquainted with SELinux and have the
system made ready for future "enforcing" mode. While running in permissive mode,
applications that are not SELinux aware will behave as if SELinux is not
running. This is perfect to validate if a problem is caused by SELinux or not:
if in permissive mode the problem still persists, then it is not caused by
SELinux.
There is one caveat though: if the application is SELinux-aware (it knows
that it can run in a SELinux environment and is able to make SELinux-specific
calls) it might still react differently. Although this is often (but not always)
a bad programming practice, some applications check if SELinux is enabled and
base their functional flow on the results, regardless of the state being
permissive or enforcing.
To find out if an application is SELinux aware, simply check if it is linked
against libselinux (with ldd or scanelf - part of
app-misc/pax-utils):
Code Listing 1.2: Checking if /bin/ls is SELinux-aware |
# scanelf -n /bin/ls
TYPE NEEDED FILE
ET_DYN libselinux.so.1,librt.so.1,libc.so.6 /bin/ls
|
Enforcing
If getenforce returns "Enforcing", then SELinux is loaded and will act
based on the policy. When a process tries some activity that is not allowed by
the policy, it will be logged (unless a dontaudit is set) and the activity will
not go through. This is the only mode where you can truely say that SELinux is
active, because it is only now that the policy is acted upon.
Switching States
Depending on your Linux kernel configuration, you can switch between states
using one of the following methods. The kernel configuration however can be made
so that some of these options are disabled (for instance, a fully hardened
system will not allow disabling SELinux in any way).
Using the command setenforce:
Code Listing 1.3: Switching between enforcing and permissive |
# setenforce 0
# setenforce 1
|
Using the kernel boot option enforcing:
Code Listing 1.4: Switching between enforcing and permissive through boot options |
kernel /kernel-2.6.39-hardened-r8 root=/dev/md3 rootflags=data=journal enforcing=0
|
Using the /etc/selinux/config SELINUX variable:
Code Listing 1.5: /etc/selinux/config SELINUX setting |
# cat /etc/selinux/config
# This file controls the state of SELinux on the system on boot.
# SELINUX can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE can take one of these four values:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.
# mls - Full SELinux protection with Multi-Level Security
# mcs - Full SELinux protection with Multi-Category Security
# (mls, but only one sensitivity level)
SELINUXTYPE=strict
|
When you want to switch from permissive to enforcing, it is recommended to do so
in the order given above:
-
First boot up in permissive mode, log on, verify that your context is
correct (id -Z) and then switch to enforcing (setenforce 1).
You can now test if your system is still working properly.
-
Next, boot with enforcing=1 as kernel parameter (unless you boot with
an initramfs, see earlier in this handbook). This way, your
system will boot in enforcing mode, but if things go haywire, you can just
reboot, leave out the option and be back in permissive mode
-
Finally, edit /etc/selinux/config to persist this change.
Domain-permissive Mode
You can also opt to mark a single domain permissive while running the rest of
the system in an enforcing state. For instance, to mark mplayer_t as a
permissive domain (which means that SELinux does not enforce anything):
Code Listing 1.6: Marking mplayer_t as permissive |
# semanage permissive -a mplayer_t
|
With the -d option, you can remove the permissive mark again.
4.b. SELinux Policy Types
Introduction
Next to the SELinux state, SELinux also offers different policy types. These
types differentiate themselves in specific SELinux features that are enabled or
disabled. Within Gentoo, three are supported (and a fourth is available):
targeted, strict, mcs (and mls).
The type used on a system is declared in /etc/selinux/config:
Code Listing 2.1: The SELINUXTYPE information in /etc/selinux/config |
# cat /etc/selinux/config
# This file controls the state of SELinux on the system on boot.
# SELINUX can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE can take one of these four values:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.
# mls - Full SELinux protection with Multi-Level Security
# mcs - Full SELinux protection with Multi-Category Security
# (mls, but only one sensitivity level)
SELINUXTYPE=strict
|
strict (without unconfined domains)
The strict policy type is the policy type that was described in the
earlier chapters, and coincidentally the type that is the easiest to understand.
With the strict policy type, each and every application runs in a domain that
has limited privileges. Although there are highly privileged domains, they are
never truely unlimited in their privileges.
targeted (using unconfined domains)
The targeted policy type is similar to the strict one, with one major
addition: support for unconfined domains. Applications (or users) that run in an
unconfined domain are almost unlimited in their privileges. The unconfined
domains are usually used for users and user applications, but also the init
system and other domains are marked as "unconfined" domains.
The idea behind the targeted policy is that network-facing services are running
in (confined) regular domains whereas the rest uses the standard discretionary
access controls offered by Linux. These other domains are running as
"unconfined".
mcs (using multiple categories)
The introduction of mls and mcs offers the ability for
multi-tenancy: multiple instances of the same application should be able
to run, but each instance should be confined with respect to the others (instead
of all these processes running in the same domain and, hence, the same
privileges).
A simple example is virtualization: a virtual guest which runs in the
qemu_t domain needs write privileges on the image file that contains the
guest operating system. However, if you run two guests, you do not want each
guest to write to the other guests' file. With regular domains, you will need to
provide this. With mcs, you can give each running instance a specific
category (number) and only grant it write privileges to the guest file with the
correct category (number).
mls (using multiple security levels)
The mls policy type is available but not yet supported by Gentoo
Hardened. With this policy type, it is possible to give sensitivity levels on
files and resources as well as domains. Sensitivity levels can best be expressed
in terms of public, private, confidential or strictly
confidential. With MLS, you can mark a file as one (or a set of)
sensitivity level(s) and ensure that only domains with the right sensitivity
level can access it.
Switching Types
It is not recommended to switch between types often. At best, you choose your
policy type at install time and stick with it. But it is not impossible (nor
that hard) to switch between types.
Make sure that your POLICY_TYPES variable in make.conf
contains the target policy type already and that the SELinux policy packages
have been built since. If that isn't the case, edit the POLICY_TYPES
variable to include the target policy type, and rebuild all SELinux policy
packages using emerge $(qlist -IC sec-policy).
Now switch your system to permissive mode using setenforce 0 or, if
your system does not allow switching the mode, edit
/etc/selinux/config to have the system boot in permissive mode. If
you cannot use setenforce 0 then you need to reboot now so that the
system is in permissive mode.
Next, edit /etc/selinux/config and change the SELINUXTYPE
variable from the current policy type to the new one. This will tell SELinux to
load the right policy at boot time.
Now go to the built policy modules in /usr/share/selinux because we
need to load in the new policy (as you are currently still running with the old
type). The next example shows how to do this if you come from a strict
policy type and want to go to mcs:
Code Listing 2.2: Loading in the mcs policy |
# cd /usr/share/selinux/mcs
# semodule -b base.pp -i $(ls *.pp | grep -v base.pp | grep -v unconfined.pp)
|
You are now running with the mcs policy loaded, but will have lots of denials if
you do anything on the file system, because the files on your file system are
not labeled correctly: the mcs policy type requires the labels to have a
sensitivity label on them, which isn't the case if you use the strict policy. So
let's relabel the entire file system, including those locations that might be
hidden because other file systems are mounted on top of it.
Code Listing 2.3: Relabeling the entire file system |
# rlpkg -a -r
# mount -o bind / /mnt/gentoo
# setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/dev
# setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/lib64
# umount /mnt/gentoo
|
Finally, edit /etc/fstab and update the rootcontext=
parameters to include a sensitivity label as well (in case you switched towards
mcs or mls) or not anymore (in case you switched to targeted or strict).
Code Listing 2.4: Changing /etc/fstab |
tmpfs /tmp tmpfs defaults,noexec,nosuid,rootcontext=system_u:object_r:tmp_t:s0 0 0
|
With all these steps now completed, reboot to ensure that everything is still
working correctly (even the boot-up).
5. Modifying the Gentoo Hardened SELinux Policy
5.a. SELinux Policy Language
Introduction
By default, Gentoo provides a generic, yet tightly controlled policy which is
deemed a good start policy for the majority of users. However, the purpose
behind a Mandatory Access Control system is to put the security administrator in
control. As such, a handbook on SELinux without information on how to write
policies wouldn't be complete.
In this chapter, we'll talk a bit about the language behind SELinux policies and
give some pointers on how to create your own policies, roles, etc.
Building a SELinux Module
First, before we go into the art of SELinux policy writing, let's first make a
small SELinux module with a rule we can test, build the module and see if things
work. Although these steps are fairly easy, they are important nonetheless.
Modifying the SELinux policy as offered by Gentoo is best done through
additional SELinux policy modules. Only when the core policy (the base policy)
is not to your liking should you see on using a totally different policy.
Let's start with a skeleton for a policy module we'll call testmod. You
should use simple names for the modules as the build infrastructure is quite
sensitive to special constructs. Use only letters a-z and numbers, and never
start a module name with a number.
Code Listing 1.1: Policy module skeleton |
policy_module(testmod, 1.0.0)
|
Yes, that's it. But as you can see, it is fairly empty. So let's add a rule that
allows a regular user (in the user_t domain) to read ebuild files (of type
portage_ebuild_t).
Code Listing 1.2: Policy module testmod |
policy_module(testmod, 1.0.0)
require {
type user_t;
type portage_ebuild_t;
class file { read open getattr };
class dir { read search open getattr };
}
allow user_t portage_ebuild_t:file { read open getattr };
allow user_t portage_ebuild_t:dir { read search open getattr };
|
As you can see, something as simple as allowing a user to read a file requires
quite a few privileges. The directory privileges are needed to allow a user to
navigate through the Portage tree structure whereas the file privileges are
needed for a user to be able to access and open the ebuilds. Save this file as
testmod.te.
To build the policy and convert it into the binary module that we can load into
the SELinux policy store, we can use the Makefile available in
/usr/share/selinux/strict/include (substitute strict with the
SELinux policy type you are using).
Code Listing 1.3: Building a binary policy module |
$ make -f /usr/share/selinux/strict/include/Makefile testmod.pp
|
The filename (testmod.pp) is the destination binary SELinux module
name. The Makefile will automatically look for the
testmod.te file you have in the working directory.
As a result, you should now have a file called testmod.pp. This
module file can now be loaded in the SELinux policy store as follows:
Code Listing 1.4: Loading a binary module |
# semodule -i /path/to/testmod.pp
|
Congratulations! You have now build your first SELinux policy module. If you
want to disable it, remove it through semodule -r testmod.
This method of building a policy (using the Makefile and
semodule) is something that you will need to do every time you want to
update the SELinux policy on your system. The contents of the policy however
does change as we will see in the rest of this document.
Getting the SELinux Policy Interfaces
To streamline policy development, the SELinux policy based on the reference
policy uses interfaces to access privileges within a module. If you have built
selinux-base-policy with USE="doc" then this information is
available at
/usr/share/doc/selinux-base-policy-<version>/html. It is
recommended to have this information at hand, since most policy
development/updates will be done through the interfaces offered by the policy.
If you are just interested, you can also find these interface definitions online. Mind you though,
the online resource is only the reference policy and might differ a bit from the
policy available within Gentoo.
Using Policy Interfaces
Using the policy interfaces allows you to update the policy with more readable
functions. For instance, to allow the user_t domain to call and use Portage
applications, the module could look like so:
Code Listing 1.5: Example policy to allow user_t to use portage |
policy_module(testmod, 1.0.0)
require {
type user_t;
role user_r;
}
portage_run(user_t, user_r)
|
Of course, this makes the user_t domain much more privileged than the previously
defined rules to read ebuild files: it allows the user to call portage, update
the system, etc. Of course, the user still requires the proper regular Linux
permissions (so he needs to be part of the portage group or become root).
Needless to say, we do not recommend to grant this to a regular user ;-)
5.b. Full SELinux Policy Modules
Checking Out an Isolated Module
With the above in mind, we can now go one step further and investigate a full
policy module, with both the type enforcement rules (.te file),
file contexts (.fc) and interfaces (.if).
You should know that writing a module requires you to get intimate with the
application. It isn't a matter of just hoping for the best: as a security
administrator, you will be responsible for defining what accesses are allowed
and which not. If you forget one, the application might break under the users'
hands. But if you add too much, you might grant privileges that can be abused
later on. And it will be a lot more difficult to track and remove privileges
later as you will be hesitating if the privilege is needed or not.
In this section, we will not divulge in how to write one. We have an excellent
Gentoo Hardened SELinux
Development resource that guides you in that. However, we will look into
such a full module to explain the other aspects of policy development.
Type Enforcement File
The .te file we wrote earlier is a type enforcement file.
Its purpose is to define the access rules related to the module that you are
building, but also - and more importantly - define new types (or even roles).
The example below is a snippet from a module for the skype application.
Code Listing 2.1: Snippet from skype.te |
policy_module(skype, 1.0.0)
type skype_t;
type skype_exec_t;
application_domain(skype_t, skype_exec_t)
type skype_home_t;
userdom_user_home_content(skype_home_t)
manage_dirs_pattern(skype_t, skype_home_t, skype_home_t)
manage_files_pattern(skype_t, skype_home_t, skype_home_t)
|
In the above example, three new types are declared: skype_t (which will
be used for the application), skype_exec_t (which is the label given to
the application binary) and skype_home_t (which will be used for the
users' ~/.Skype location). Also, the skype_t domain is given
some privileges with respect to the skype_home_t label (manage
directories and files).
File Context File
In the .fc file (which stands for file context file) the
module's resources (files, directories, sockets, ...) are defined. Once the
module is loaded, these rules are added so that file system relabeling will put
the correct context on the files.
The example below is a snippet from the skype modules' file context file.
Code Listing 2.2: Snippet from skype.fc |
HOME_DIR/\.Skype(/.*)? gen_context(system_u:object_r:skype_home_t,s0)
/opt/skype/skype -- gen_context(system_u:object_r:skype_exec_t,s0)
/usr/bin/skype -- gen_context(system_u:object_r:skype_exec_t,s0)
|
The format of the file context file has the following syntax:
-
The regular expression that matches the file(s) and directorie(s) affected
by that line
-
An optional identifier to differentiate the type of files (file, directory,
socket, symbolic link, ...)
-
A gen_context line that contains the context to assign to the file(s)
and directorie(s)
Interface File
In the .if file (for interface file) interfaces are declared
which can be used by other modules. It is through interfaces that a nicely
defined policy can be built on top of other, existing policy modules.
One interface could be to allow users to call and execute an application. For
instance, the following interface can be found in the skype module.
Code Listing 2.3: Snippet from skype.if |
interface(`skype_role',`
gen_require(`
type skype_t, skype_exec_t, skype_tmpfs_t, skype_home_t;
')
role $1 types skype_t;
domtrans_pattern($2, skype_exec_t, skype_t)
allow $2 skype_t:process { ptrace signal_perms };
manage_dirs_pattern($2, skype_home_t, skype_home_t)
manage_files_pattern($2, skype_home_t, skype_home_t)
manage_lnk_files_pattern($2, skype_home_t, skype_home_t)
relabel_dirs_pattern($2, skype_home_t, skype_home_t)
relabel_files_pattern($2, skype_home_t, skype_home_t)
relabel_lnk_files_pattern($2, skype_home_t, skype_home_t)
ps_process_pattern($2, skype_t)
')
|
Through this skype_role, we can then allow users to call skype, as can be
found in the unprivuser.te file (which defines the user_t domain):
Code Listing 2.4: Snippet from unprivuser.te to call skype |
optional_policy(`
skype_role(user_r, user_t)
')
|
The following table shows a few common interfaces that could be in use. We
seriously recommend to look at the available interfaces when enhancing or
creating your own modules - and be sure to pick the interface that adds just
what you need, nothing more.
| Templates |
| Suffix |
Example |
Description |
| _template |
virt_domain_template(prefix) |
Not really an interface, templates create additional domains based on the
information given to them. This is usually done for fine-grained policy
templates with a common (sub)set of privileges.
|
| Transformations |
| Suffix |
Example |
Description |
|
miscfiles_cert_type(resource) |
Transformation interfaces generally add specific attributes to resources or
domains. Attributes "transform" the given resource into something more. In
the given example, the miscfiles_cert_type(resource) assigns the cert_type
attribute to the resource (and also marks it as a file). Interfaces, like
miscfiles_read_all_certs work on these attributes.
|
| Access interfaces |
| Suffix |
Example |
Description |
| _<access>_<resource> |
mta_getattr_spool(domain) |
Grant the specified domain access towards the shown resource. The resource
usually defines the type too (like kudzu_getattr_exec_files: grant getattr
on the kudzu_exec_t files) unless it is obvious from the name, or when the
resource is a more specific term towards the domain. It can also include
dontaudit (like mta_dontaudit_getattr_spool).
|
| _exec |
dmesg_exec(domain) |
Grant one domain the right to execute the given domains' executable file (in
the example, allow "domain" to execute dmesg_exec_t files), but without
implying that the domains transition. In other words, dmesg gets executed
but still confined by the privileges of the source domain.
|
| _domtrans |
dmesg_domtrans(domain) |
Grant one domain execute and transition privileges towards the new domain.
This interface is most commonly used to allow application domains to
transition to another. In the given example, dmesg is ran with the
privileges of the dmesg_t domain.
|
| _run |
netutils_run(domain, role) |
Grant a given role and domain the rights to execute and transition towards
the given domain. This is usually granted to (existing) user roles and
domains and gives them the set of privileges needed to interact safely with
the new (interactive) domain (such as terminal access).
|
| _role |
xserver_role(role, domain) |
Allow the given role and domain the necessary permissions to transition and
interact with the given domain. This interface is enhanced with the
privileges to interact with the domain (and its underlying files) more
thoroughly, and is usually assigned to newly created users or roles within
the policy (rather than enhance existing user domains and roles).
|
| _admin |
aide_admin(domain) |
Grant the given domain the rights to administer the target domains'
environment. This usually involves privileges to manage and relabel all
affiliated files, directories, sockets, etc.
|
5.c. Using audit2allow
Introduction
When reading online resources on SELinux, you will notice that there are many
references to a tool called audit2allow. This tools' purpose is to read
AVC denial messages from the audit log file and transform them into a policy
module that you can load. The advantage is that it makes it a lot easier to
write policies. The downside is that the output (unless you use the -R
option) is not usable for the Makefile we used earlier to build
modules.
Another disadvantage is that the tool does not intelligently cope with changes.
It blindly accepts denials and treats them as if they need to be allowed, rather
than investigate if no other context should be given to the file, etc.
Using audit2allow
Using audit2allow is pretty straightforward. You send it the denials you
want to fix and store the result in a .te file. You then convert it
into an intermediary format which can then be translated into a .pp
file for final loading by semodule.
For instance, to catch all denials and transform them into allowed statements
from firefox-related denials:
Code Listing 3.1: Generate a new policy using audit2allow |
# grep firefox /var/log/avc.log | audit2allow -m firefoxmod > firefoxmod.te
# checkmodule -m -o firefoxmod.mod firefoxmod.te
# semodule_package -o firefoxmod.pp -m firefoxmod.mod
# semodule -i firefoxmod.pp
|
Keep the module name (given through the -m option) simple: only use
characters ([a-z]) and numbers ([0-9]), and start the module name
with a character.
5.d. Creating Additional Roles
Create the Role and Domain
If you want to create additional roles on the system, you first need to create a
SELinux module that creates that role, together with its main domain. Below is a
very simple example for a database administration role, which we will offer
through the sec-policy/selinux-dbadm package later:
Code Listing 4.1: Example dbadm_r and dbadm_t definition |
policy_module(dbadm, 1.0.0)
#######################################
#
# Declarations
#
role dbadm_r;
# Create a user domain (dbadm_t)
userdom_base_user_template(dbadm)
#######################################
#
# dbadm local policy
#
allow dbadm_t self:capability { dac_override dac_read_search sys_ptrace };
files_dontaudit_search_all_dirs(dbadm_t)
files_delete_generic_locks(dbadm_t)
files_list_var(dbadm_t)
selinux_get_enforce_mode(dbadm_t)
logging_send_syslog_msg(dbadm_t)
userdom_dontaudit_search_user_home_dirs(dbadm_t)
optional_policy(`
# Grant the user admin rights on PostgreSQL (process-wise)
postgresql_admin(dbadm_t, dbadm_r)
')
|
Build and load the module and verify that the role is now available:
Code Listing 4.2: Build and verify |
# make -f /usr/share/selinux/strict/include/Makefile dbadm.pp
# semodule -i dbadm.pp
# seinfo -r | grep dbadm
dbadm_r
|
Assign Users the Role
Next, assign users the role you just created. You can do this to existing
SELinux users, but here we'll create an additional SELinux user for the role.
Code Listing 4.3: Grant a user the role |
# semanage user -a -R "staff_r dbadm_r system_r" dbadm_u
|
Next map the user(s) to this SELinux user.
Code Listing 4.4: Mapping a set of users to the dbadm_u user |
# semanage login -a -s dbadm_u david
# semanage login -a -s dbadm_u laura
|
Also load in the following policy to support transitioning to the dbadm_r role
for the staff_r role:
Code Listing 4.5: Allow transitioning to dbadm_r |
dbadm_role_change(staff_r)
|
In the first semanage command, where we create the dbadm_u user, you
might have noticed that we grant it the system_r role. This is because
the user is granted the postgresql_admin role, allowing the user to
manipulate the postgresql init script:
Code Listing 4.6: User restarting postgresql service |
$ ls -Z /etc/init.d/postgresql
system_u:object_r:postgresql_initrc_exec_t /etc/init.d/postgresql
$ sudo -r dbadm_r -t dbadm_t /etc/init.d/postgresql restart
|
Thanks to the SELinux support by sudo, you can also mention the role and
type in the sudoers file:
Code Listing 4.7: Using the sudoers file for specific roles |
david ALL=(ALL) ROLE="dbadm_r" TYPE="dbadm_t" NOPASSWD: /etc/init.d/postgresql [a-z]*
|
With this setting, the user can just run sudo /etc/init.d/postgresql
restart.
By using sudo correctly, you can grant the user full administrative
rights over a daemon (including editing files) with a much lower risk of the
user elevating his rights to a more system-wide administrative role.
The idea behind this approach is that the user stays within its main domain
(like staff_t) but is allowed to perform administrative actions through
sudo which allow him to (temporarily) transition to the dbadm_r
role.
6. Troubleshooting SELinux
6.a. Unable To Load SELinux Policy
Problem Description
If you notice that SELinux is not functioning at all, a quick run of
sestatus should give you closure if SELinux is enabled and loaded or not.
If you get the following output, no SELinux policy is loaded:
Code Listing 1.1: sestatus output |
SELinux status: disabled
|
If this is the case, read on in this section to find out how to troubleshoot and
resolve this.
No Policy Installed
One potential reason would be that there is no policy to load to begin with.
Take a look inside /usr/share/selinux/strict or
/usr/share/selinux/targeted (depending on your configuration) and
look for a file called base.pp. If no such file exists, you will
need to install the base policy. This policy is offered by the
sec-policy/selinux-base-policy package, but it is better to read up
on the chapter regarding Gentoo SELinux
Installation / Conversion as more important changes might be missing.
Policy Not Loaded
If the base.pp file exists in
/usr/share/selinux/strict (or targeted/), take a look
inside /etc/selinux/strict/policy. This location too should contain
a base.pp policy module (when a SELinux policy is loaded, it is
copied from the first location to the second).
If no base.pp file exists, install and load the policy:
Code Listing 1.2: Installing the base policy |
~# semodule -n -B
|
This is a one-time operation - once installed and loaded, it will be reloaded
upon every reboot.
Init Can Not Load the SELinux Policy
During system boot, the init process is responsible for loading and
interacting with the SELinux policy in memory. If init does not support
SELinux, you will get no SELinux support in your environment.
To verify if init supports SELinux, we need to check if it uses the
libselinux.so shared object:
Code Listing 1.3: Checking if init supports SELinux |
~# ldd /sbin/init
linux-vdso.so.1 => (0x00006ace30e84000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00006ace30a46000)
libc.so.6 => /lib/libc.so.6 (0x00006ace306e9000)
libdl.so.2 => /lib/libdl.so.2 (0x00006ace304e5000)
/lib64/ld-linux-x86-64.so.2 (0x00006ace30c68000)
|
If this is not the case, make sure that emerge --info shows that the
selinux USE flag is in place, and reinstall sys-apps/sysvinit. If
the selinux USE flag is not in place, check your Gentoo profile and make sure it
points to a selinux/v2refpolicy/... profile.
Policy Store is Corrupt
If you encounter problems during boot-up or semodule operations which
fail with loading problems, but cannot be resolved with the above solution, then
you might need to reinstall the policies after eliminating the corrupt store.
Code Listing 1.4: Recovering from store corruption |
~# semodule -n -B
libsemanage.semanage_load_module: Error while reading from module file
/etc/selinux/targeted/modules/tmp/base.pp. (No such file or directory)
~# setenforce 0
~# mv /etc/selinux/targeted /etc/selinux/targeted.old
~# FEATURES="-selinux" emerge -1av $(qlist -IC sec-policy)
~# restorecon -R /etc/selinux
|
This will effectively disable the current, corrupted SELinux policy store and
then use Portage to reinstall all SELinux policy packages that are installed on
the system. When done, the file contexts of /etc/selinux are
restored, after which you should be able to continue.
6.b. Unable to Log On
Problem Description
If you are unable to log on in a particular situation (remote, local, as root,
as regular user, ...) there are a few possible problems which you might have
hit. However, to resolve them you'll need to be able to log on to the system as
sysadm_r in one way or the other.
If you can not log in as a sysadm_r user, disable SELinux (boot with
enforcing=0) so that no SELinux enforcements are made. Changes that you
make in permissive mode are equally effective as in enforcing mode.
Incorrect Context
In the majority of cases will you find that a security context is incorrect. Run
sestatus -v and compare the Process contexts or File
contexts that you see in the output with the next table.
| Process |
Context |
If wrong context... |
| Init context |
system_u:system_r:init_t |
First, verify that init itself is correclty labeled. Check the output of
the previously run sestatus -v command for the
/sbin/init file and make sure that it is set to
system_u:object_r:init_exec_t. If that is not the case, relabel
sys-apps/sysvinit using rlpkg sysvinit. Also make the
same checks as in the Unable To Load SELinux
Policy section. Reboot your system and retry.
|
| agetty context |
system_u:system_r:getty_t |
Make sure that the /sbin/agetty binary is labeled
system_u:object_r:getty_exec_t. If not, relabel the
sys-apps/util-linux package using rlpkg util-linux. Then
restart all the agetty processes using pkill agetty (they will
automatically respawn).
|
| File |
Context |
If wrong context... |
| /bin/login |
system_u:object_r:login_exec_t |
The login binary is part of sys-apps/shadow. Run rlpkg
shadow to relabel the files of that package and retry logging in.
|
| /sbin/unix_chkpwd |
system_u:object_r:chkpwd_exec_t |
This binary is part of the sys-libs/pam package and is used by
SSH when it is configured to use PAM for user authentication. Relabel the
package using rlpkg pam and retry logging in.
|
| /etc/passwd |
system_u:object_r:etc_t |
The /etc/passwd and /etc/shadow must be labeled
correctly, otherwise PAM will not be able to authenticate any user. Relabel
the files through restorecon /etc/passwd /etc/shadow and retry
logging in.
|
| /etc/shadow |
system_u:object_r:shadow_t |
| /bin/bash |
system_u:object_r:shell_exec_t |
The users' shell (in this case, bash) must be labeled correctly so
the user can transition into the user domain when logging in. To do so,
relabel the app-shells/bash package using rlpkg bash.
Then, try logging in again.
|
6.c. Unable to Emerge Anything (OSError: [Errno 22] Invalid argument)
Problem Description
When trying to install software with Portage, you get a huge python stacktrace
and finally the error message OSError: [Errno 22] Invalid argument:
Code Listing 3.1: Stacktrace dump when portage fails to install software |
Traceback (most recent call last):
File "/usr/bin/emerge", line 43, in <module>
retval = emerge_main()
File "/usr/lib64/portage/pym/_emerge/main.py", line 1906, in emerge_main
myopts, myaction, myfiles, spinner)
File "/usr/lib64/portage/pym/_emerge/actions.py", line 437, in action_build
retval = mergetask.merge()
...
File "/usr/lib64/portage/pym/portage/package/ebuild/doebuild.py", line 104, in _doebuild_spawn
return spawn(cmd, settings, **kwargs)
File "/usr/lib64/portage/pym/portage/package/ebuild/doebuild.py", line 1255, in spawn
return spawn_func(mystring, env=mysettings.environ(), **keywords)
File "/usr/lib64/portage/pym/portage/_selinux.py", line 105, in wrapper_func
setexec(con)
File "/usr/lib64/portage/pym/portage/_selinux.py", line 79, in setexec
if selinux.setexeccon(ctx) < 0:
OSError: [Errno 22] Invalid argument
|
Wrong Context
The above error comes when you launch portage (through emerge) while you
are not in sysadm_t context. You can verify this with id -Z:
Code Listing 3.2: Checking current context |
~# id -Z
system_u:system_r:local_login_t
|
As long as the context isn't sysadm_t, then Portage will break. This is
because Portage wants to switch its execution context from portage_t to
portage_sandbox_t but fails (it isn't in portage_t to begin with
because the user who launched Portage isn't in sysadm_t).
Please check Unable to Log On above first. Also
make sure that you can dispatch-conf or etc-update after
installing SELinux so that /etc/pam.d/system-login is updated with
the right pam_selinux.so calls.
Forcing Installation
If you need to force Portage to continue regardless (for instance, you were in
the middle of a SELinux installation so cannot properly resolve such issues
now), run the emerge command but with FEATURES="-selinux". This
will effectively disable Portage' SELinux integration, but allows you to
continue installing software.
Code Listing 3.3: Running emerge without selinux support |
~# FEATURES="-selinux" emerge -u world
|
Make sure that you relabel the entire file system after using this approach!
Portage will not label the files installed on the system correctly if you
disable its SELinux support. To relabel the entire file system, use rlpkg -a
-r.
7. Change History
7.a. Introduction
About this document
This document will give an overview of all SELinux documented changes made
on particular dates and that might be important for users to follow up through.
Changes that only affect ~arch users will be documented below and moved up when
they are stabilized. It is possible though that these changes will be "fixed"
automatically and as such removed from this page.
7.b. Overview of Changes for Stable Users
2013/04/16 - Introduce selinux_gentoo init script
With policycoreutils-2.1.13-r8 and later, we now provide our own init script
selinux_gentoo, which includes the necessary support for the
initramfs users, but also resets the contexts of dynamically generated resources
(on pseudo file systems) which are different from the default setting.
The first user here is /sys/devices/system/cpu/online which gets
labeled cpu_online_t (from revision 13 of the SELinux policy, or when using live
ebuilds for the policy).
The init script will by default also restore the contexts of all
/dev devices (unless you boot with the norestorecon option)
and will switch to enforcing mode if /etc/selinux/config has
SELINUX=enforcing set but the user booted with enforcing=0 (unless
you boot with nosetenforce option).
This means that users are now encouraged to add this init script to the boot
runlevel:
Code Listing 2.1: Adding selinux_gentoo to the boot runlevel |
# rc-update add selinux_gentoo boot
|
2012/12/04 - Introduce USE=unconfined
From selinux-base-2.20120725-r9 onwards, we will now also support
a USE=unconfined setting. When enabled, it will configure your SELinux
policy to support the unconfined domains. If your policy is targeted,
this behavior will be implied, whereas the strict policy will not
consider this USE flag at all (it will not activate unconfined domains on
strict).
Supporting this USE flag allows us to differentiate unconfined domains versus
regular ones when using the mls or mcs policy types. When set, the
selinux-unconfined package will be built as well, and the module
will be loaded, and the policy seusers file (which contains the
default domain mappings for users) will be updated to use the
unconfined_u SELinux user for root and other users.
2012/08/16 - Adding system_r role to admins
Since selinux-base-2.20120725-r3 and later, init scripts will now
support the upstream "labeled" init script approach. This means that those
services whose init script follows the <domain>_initrc_exec_t
naming convention can now be assigned to specific users (allowing those to
manage the services without the need to grant them system administration
rights).
The downside of this approach is that the system administrator itself (who uses
the sysadm_t domain) now also needs to be granted the right to manage
those services. And granting this right means that the SELinux user (be it
root or staff_u) needs to be granted the system_r role:
Code Listing 2.2: Granting system_r role |
# semanage user -a -R "staff_r sysadm_r system_r" root
# semanage user -a -R "staff_r sysadm_r system_r" staff_u
|
2012/06/24 - Definition of /run in fstab
The /run location needs to be mounted with the var_run_t
context. To do so, /etc/fstab needs to be modified as per the
instructions in Setting the
filesystem contexts.
2012/05/26 - Support of initramfs
Users who boot with an initramfs will need to boot in permissive mode first, and
later on switch to enforcing mode. This can be done automatically using an
init script, as documented at Initramfs
users.
2012/05/26 - Support for graphical login managers
Users who boot into a graphical environment (such as through GDM) will need to
edit their PAM configuration files accordingly to support SELinux security
context settings. This is documented at Users
of a graphical environment.
2012/05/18 - No more sandbox configuration needed
The previously documented editing of /etc/sandbox.conf to open
write access to /sys/fs/selinux/context can be removed as the
SELinux profile does this now automatically.
2012/04/29 - Edit of lvm-start/stop scripts no longer needed
When users install the newly stabilized 2.20120215 policies, the documented
editing of /lib/rcscripts/addons/lvm-st*.sh is no longer needed.
2012/02/21 - /dev mount line in fstab no longer needed
The previously documented /dev mount line in /etc/fstab is no
longer needed as util-linux-2.20.1-r1 has been marked stable (which
contains the correct bug fix).
2011/12/10 - Deprecation of selinux/v2refpolicy/* profiles
The old SELinux profiles (starting with selinux/v2refpolicy) are not
supported anymore. Users are strongly encouraged to switch to the new profiles
(those ending with /selinux).
2011/07/22 - Introduction of MLS/MCS support
We now support MLS and MCS, right next to targeted and strict SELinux policy
types. When using MLS or MCS, you will need to update the /tmp
entry in your /etc/fstab to use
rootcontext=system_u:object_r:tmp_t:s0 (note the trailing :s0).
7.c. Overview of Changes for ~Arch Users
2013/04/19 - Introducing selocal command
With policycoreutils-2.1.13-r11 onwards, a new command called selocal is
available. This command allows users to easily add in additional SELinux policy
rules to the local policy without having go through the hassle of building and
maintaining their own .te files. Instead, this command does that
for you.
Rules that are added to the local policy (hence the name, selocal) can be
accompanied with a small comment to allow users to describe why a change was
added (or to refer to a bug id on Gentoo's bugzilla).
Code Listing 3.1: Adding a rule to the local policy |
# selocal -a "rpcbind_stream_connect(sysadm_t)" -c "Be able to call exportfs (NFS)"
# selocal --build --load
|
With --list you can view the currently added local policy rules, and with
--delete they can be removed from the local policy. When you want to have
the changes take effect, run selocal --build --load to build the new
local policy and load it in memory.
The contents of this document, unless otherwise expressly stated, are licensed under the CC-BY-SA-2.5 license. The Gentoo Name and Logo Usage Guidelines apply.
|