Using substitution definitions
Sometimes, applications and their resources get installed at different locations than expected by the SELinux policy. Trying to accommodate this by defining additional context definitions for each and every subdirectory can easily become unmanageable.
To help administrators, the SELinux utilities support substitution entries, which tell SELinux "if a path starts with this, then label it as if it starts with that". Administrators can set such a substitution (which is called an equivalence class) using semanage
, as follows:
~# semanage fcontext –a –e / /mnt/chroots/bind
In this example, any location under /mnt/chroots/bind/
will be labeled as if it started from the main /
directory (so /mnt/chroots/bind/etc/
becomes etc_t
as /etc/
is etc_t
).
Target locations for chroots
are a good use case for this. A chroot
is an alternate location on the filesystem, which will act as the root filesystem for one or a set of applications.
For administrators who want to set substitutions across multiple systems, it is not possible to make this part of an SELinux policy module. The file that we need to manage is called file_contexts.subs
(there is also one that ends with .subs_dist
and is managed by the Linux distribution, which we will not touch). Having that said, we can always look at how to update this file in a more or less sane manner.
Getting ready
The easiest method would be to use a central configuration management utility, such as Puppet, CFEngine, Chef, or Ansible, as these systems allow administrators to force the content of specific files to a particular value. The use of a configuration management tool is an entire book in itself, so this is outside the scope of this book. If you do want to pursue this, remember that the file_contexts.subs
file is (also) managed by the semanage
command. Administrators might want to add in local definitions that the central configuration management utility isn't aware of (and thus might revert the change).
In this recipe, we'll cover a generic approach, but it does require that there is a way to do both a file transfer followed by a single line command (executed with proper permissions). This, however, shouldn't be much of a challenge to most system administrators.
How to do it…
In order to apply changes to a wide range of systems, follow the next set of steps:
- Apply the change locally to the system:
~# semanage fcontext -a -e / /mnt/chroot/bind
- Export the definitions to a single file:
~# semanage export -f local_selinux.mods
- Edit the
local_selinux.mods
file and remove all entries that are not related to the change but need to be distributed. - Distribute the resulting file to the target systems.
- Apply the changes locally to the system:
~# semanage import -f local_selinux.mods
How it works…
The semanage fcontext
command instantiates an equivalence class for /mnt/chroot/bind/
, which has all subdirectories and files inside of it labeled as if they were at /. This ensures that administrators do not need to define a large amount of file contexts for each and every chroot
location they manage.
However, this might become problematic as semanage fcontext
only applies changes locally, and on a larger infrastructure, the same settings might need to be applied to multiple systems. For this, semanage export
and semanage import
can be used.
The output of the semanage export
command is a set of instructions for semanage
and follows the syntax of the semanage
commands to the letter.
When exporting the semanage
definitions, the first set of commands that are stored are the delete all
statements such as fcontext -D
(delete all locally made semanage fcontext
settings). Of course, if we only need to distribute the substitution definitions, then deleting all previously made local statements is incorrect. Hence, the need to manually edit the local_selinux.mods
file. If only the equivalence class definition needs to be distributed, then the file might just contain the following:
fcontext -a -e / /mnt/chroot/bind
The exported file can then be distributed to all target systems and loaded through the semanage import
command effectively applying the same set of changes to the system.
If the definition was already applied on a system, then the import
command will fail:
~# semanage import -f local_selinux.mods ValueError: Equivalence class for /mnt/chroot/bind already exists
It is important to note here that if one command in the file fails to apply, then none of the commands in the file are applied (the file is processed in one go). This is why the delete all
rules are originally made part of the exported set of commands.
This makes distributed management of such settings more challenging if locally applied changes need to be kept as well, unless the distributed set of changes are singular (one exported instruction, which is allowed to fail).
There's more...
Most files inside the /etc/selinux/mcs/contexts/
location shouldn't be managed through any tool except either the Linux distribution package management system (through the installation of the base SELinux policy) or semanage
.
That being said, most files inside this location don't change much (except for the files/file_contexts
file). It might be beneficial to hook into the package management system to update these files (if supported) or bluntly take over the management of these files, assuming you track the changes that the distribution would make closely.
See also
The following resources dive deeper into the topics discussed in this recipe:
- To find out more about the various configuration files, check out http://selinuxproject.org/page/PolicyConfigurationFiles
- The interaction of SELinux with
chroots
is discussed in more detail in Chapter 9, Aligning SELinux with DAC