SELinux Cookbook
上QQ阅读APP看书,第一时间看更新

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:

  1. Apply the change locally to the system:
    ~# semanage fcontext -a -e / /mnt/chroot/bind
    
  2. Export the definitions to a single file:
    ~# semanage export -f local_selinux.mods
    
  3. Edit the local_selinux.mods file and remove all entries that are not related to the change but need to be distributed.
  4. Distribute the resulting file to the target systems.
  5. 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: