SELinux file context expressions

June 07, 2021

When we think that the context of a file is wrong, we need to correct the context. SELinux offers several methods to do so, and some distributions even add in more. We can use tools such as chcon, restorecon (together with semanage), setfiles, rlpkg (Gentoo), and fixfiles. Of course, we could also use the setfattr command, but that would be the least user-friendly approach for setting contexts.

Let’s see how we can set context expressions in a more manageable way.

Using context expressions

In the SELinux policy, a list of regular expressions is kept that informs the SELinux utilities and libraries what the context of a file (or other filesystem resource) should be. Though this expression list is not enforced on the system directly, administrators and SELinux utilities use it to see whether a context is correct, and to reset contexts to what they are supposed to be. You can find the list itself in /etc/selinux/targeted/contexts/files in the various file_contexts.* files.

As an administrator, we can query this list through semanage fcontext as follows:

# semanage fcontext -l
SELinux fcontext	type		Context
/			directory	system_u:object_r:root_t:s0
...
/vmlinuz.*		symbolic link	system_u:object_r:boot_t:s0
/xen(/.*)?		all files	system_u:object_r:xen_image_t:s0
...

An example of a tool that queries this information is matchpathcon, Understanding SELinux Decisions and Logging:

# matchpathcon /srv/web/localhost/htdocs/dokuwiki
/srv/web/localhost/htdocs/dokuwiki system_u:object_r:var_t:s0

Not all the entries are visible through the semanage application though. Entries related to specific user home directories (such as /home/lisa/.ssh) are not shown as these entries depend on the Linux user (and, more importantly, its associated SELinux user).

But for all other entries, the output of the command contains the following:

  • A regular expression that matches one or more paths
  • The classes to which the rule is applicable, but translated into a more human-readable format
  • The context to assign to the resources that match the expression and class list

The class list allows us to differentiate contexts based on the resource class. The semanage fcontext output uses human-readable identifiers: resource classes can be a regular file (--), a directory (-d), a socket (-s), a named pipe (-p), a block device (-b), a character device (-c), or a symbolic link (-l). When it says all files, the line is valid regardless of the class.

Right now, we have not defined such rules yet, but after the next section, even defining custom SELinux context expressions will no longer hold any secrets. An important property of the context list is how SELinux prioritizes its application – after all, we could easily have two expressions that both match a certain resource or path. Within SELinux, the most specific rule wins. The logic used is as follows (in order):

  • If line A has a regular expression and line B doesn’t, then line B is more specific.
  • If the number of characters before the first regular expression in line A is less than the number of characters before the first regular expression in line B, then line B is more specific.
  • If the number of characters in line A is less than in line B, then line B is more specific.
  • If line A does not map to a specific SELinux type (the policy editor has explicitly told SELinux not to assign a type) and line B does, then line B is more specific.

There is a caveat with the rule order, however. When additional rules are added through semanage (which we describe in the next section), then SELinux’s utilities apply the rules in the order they were added rather than their specificity. So, instead of the most specific rule, the most recently added rule that matches the path is used.

Registering file context changes

Because changing an SELinux context using chcon is often just a temporary measure, it is seriously recommended to only use chcon when testing the impact of a context change. Once the change is acceptable, we need to register it through semanage. For instance, to permanently mark /srv/web (and all its subdirectories) as httpd_sys_content_t, and the DokuWiki data/ and conf/ folders as httpd_sys_rw_content_t (to allow the web server to modify these resources), we need to execute the following:

# semanage fcontext -a -t httpd_sys_content_t "/srv/web(/.*)?"
# semanage fcontext -a -t httpd_sys_rw_content_t "/srv/web/localhost/htdocs/dokuwiki/data(/.*)?"
# semanage fcontext -a -t httpd_sys_rw_content_t "/srv/web/localhost/htdocs/dokuwiki/conf(/.*)?"
# restorecon -Rv /srv/web

What we do here is register /srv/web and its subdirectories as httpd_sys_content_t and the two writable directories as httpd_sys_rw_content_t through semanage. Then, we use restorecon to (recursively) reset the contexts of /srv/web to the value registered in the context list. This is the recommended approach for setting contexts on most resources.

These registrations are local (custom) context expressions and are stored in a separate configuration file (file_contexts.local). Considering the priority of (locally added) expressions, it is important to have the most specific entries added last, as otherwise the more broadly defined rule for httpd_sys_content_t would be applied to the entire directory. This is unlike the priority rules for (policy added) expressions that do have the concept of most specific rule wins.

The semanage fcontext application can also be used to inform SELinux that a part of the filesystem tree should be labeled similarly as a different location on the filesystem. Such an equivalency rule allows us to use different paths for application installations or file destinations and tell semanage to apply the same contexts as if the destination were the default.

Let’s make this more visible through an example, and have everything under /srv/web be labeled in a similar manner to the files at /var/www (including subdirectories), so /srv/web/icons gets the same context as /var/www/icons. We use the -e option of semanage fcontext to create such an equivalency as follows:

# semanage fcontext -a -e /var/www /srv/web
# restorecon -Rv /srv/web

This will create a substitution entry so that anything under /srv/web gets the same label as if it were at the same location under /var/www.

Most distributions already configure a few equivalency rules that we can read as follows:

# cat /etc/selinux/targeted/contexts/files/file_contexts.subs_dist
/run /var/run
...
/sysroot/tmp /tmp

The semanage fcontext -l command will show these equivalent locations at the end of its output as well.

Optimizing recursive context operations

The restorecon application resets the SELinux context of files and other resources based on the context definitions managed through the SELinux policy and semanage fcontext. When applying restorecon in a recursive fashion against directories, this might take a while. To improve performance in this situation, the SELinux authors support the skipping of restorecon operations.

With the -D option to restorecon, an additional extended attribute will be written to the main directory that contains a hash of the file context definitions used when invoking the command:

# restorecon -RD /home

Subsequent invocations of restorecon with -D will check this hash to see whether any of the file context definitions that impact this directory have been modified (using semanage fcontext). If there aren’t, then the restore operation will be skipped:

# restorecon -RvD /home
Skipping restorecon as matching digest on: /home

Once we update a definition that influences the given location, then restorecon will reset the contexts appropriately:

# semanage fcontext -a -t httpd_user_content_t "/home/[^/]*/cgi-bin(/.*)?"
# restorecon -RvD /home
Relabeled /home/lisa/cgi-bin from staff_u:object_r:user_home_t:s0 to staff_u:object_r:httpd_user_content_t:s0
Updated digest for: /home

The restorecon_xattr command can be used to manage these extended attributes (view or delete) and show how the attributes are formed:

# restorecon_xattr -v /home
specfiles SHA1 digest: 7ed69be330ad60811481e455ca8e5ab0b1556036
calculated using the following specfile(s):
/etc/selinux/targeted/contexts/files/file_contexts.subs_dist
...
/etc/selinux/targeted/contexts/files/file_contexts.local.bin
/home Digest: 7ed69be330ad60811481e455ca8e5ab0b1556036 Match

The digest referenced is the security.restorecon_last or security.sehash extended attributes. More recent user space tools use the latter, and apply their logic to each subdirectory, whereas older user space utilities use the former and only apply their logic on the selected directory.

The disadvantage of the security.restorecon_last usage is that it does not work with subdirectories: if we apply a recursive restorecon operation against /, then this tool will ignore the digest on /home. With the security.sehash usage, a recursive operation against / will check the digest for /home as well.

Using customizable types

Some SELinux types are meant for files whose paths cannot be accurately defined by administrators or where the administrator does not want the context to be reset when a relabeling operation is triggered. For these purposes, SELinux supports what it calls customizable types. When tools that manage file contexts (such as restorecon) encounter a file with a customizable type set, they will not revert its context to the registered context definition.

The customizable types are declared in the customizable_types file inside /etc/selinux/targeted/contexts. To have restorecon relabel such files, administrators need to pass the force reset option (-F) before the tool resets the contexts.

Let’s look at the contents of this customizable_types file:

$ cat /etc/selinux/targeted/contexts/customizable_types
container_file_t
sandbox_file_t
...
httpd_user_content_t
git_session_content_t
home_bin_t
user_tty_device_t

As an example, we can mark a file in a home directory as home_bin_t, which is a customizable type, and as such, this file will not be relabeled back to user_home_t when a filesystem relabeling operation is done:

$ chcon -t home_bin_t ~/convert.sh

Marking other types as customizable requires updating the customizable_types file, as there is no user command that adds or removes type definitions from this list. Because this file can be overwritten when the distribution or administrator pushes out a new policy package, it needs to be governed carefully.

That said, the use of customizable types has its advantages. As an administrator, we might want to create and support specific types as usable by end users who can use chcon to set the contexts of individual files in their home directory. By having those types marked as customizable types, a relabeling operation against /home will not reset those contexts.

When the target type is not a customizable type, administrators generally prefer to use semanage fcontext to add an expression and restorecon to fix the context of the files. Most administrators will use directory-based labeling: this is much easier to maintain, and much easier to explain to end users. Many will even use this approach for customizable types:

# semanage fcontext -a -t home_bin_t "/home/[^/]*/bin(/.*)?"

With this command, user binaries and scripts located in the ~/bin directory will be labeled as home_bin_t.

Compiling the different file_contexts files

Inside the /etc/selinux/targeted/contexts/files directory, five different  file_contexts  files can be found:

  • The file_contexts file itself (without any suffix) is the basic expression file provided by the SELinux policy offered through the Linux distribution.
  • The file_contexts.local file contains the locally added rules (through the semanage fcontext command, which we covered earlier in this chapter).
  • The file_contexts.homedirs file contains the expressions for the user home directories. When new user mappings are created and managed through semanage login and semanage user, this file is adjusted to reflect the new situation.
  • The file_contexts.subs_dist file contains equivalency rules, provided by the distribution’s SELinux policy, which tell SELinux to consider one part of the filesystem as having the same labeling rules as another location.
  • The file_contexts.subs file contains locally managed equivalency rules (through the semanage fcontext command).

Alongside those files, you will find associated *.bin files (so file_contexts.bin for the file_contexts file, file_contexts.local.bin for the file_contexts.local file, and so on). These *.bin files are automatically created, but in case of a discrepancy, administrators can rebuild the files themselves as well using the sefcontext_compile command:

# cd /etc/selinux/targeted/contexts/files
# sefcontext_compile file_contexts.local

These files contain the same information as the main file, but are precompiled to make lookups faster. Unless the tools detect that the *.bin files are older than their source files, the SELinux utilities will use the compiled versions of these files.

Exchanging local modifications

When local modifications are registered through semanage fcontext, they only apply to a single system. If local definitions need to be reapplied on various systems, administrators can extract the local modifications and import them on another system.

To export the local modifications, use semanage export:

# semanage export -f local-mods.conf

The file that contains the local modifications (local-mods.conf in the example) can be adjusted at will. This allows administrators to remove all lines except those they want to apply on other systems.

With the local modifications stored in the file, transport the file to the other system(s) and import the settings:

# semanage import -f ./local-mods.conf

The imported settings are immediately registered. Of course, in case of filesystem changes (semanage fcontext), don’t forget to run restorecon against the target directories.

Related Articles

No Results Found

The page you requested could not be found. Try refining your search, or use the navigation above to locate the post.

Lorem ipsum dolor sit amet consectetur

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

6 + nine =