SELinux – Editing a file’s Security Context


By the end of this article you should be able to answer the following questions:


You can find all my latest posts on medium.

What is the command to give you an insight in how SELinux determines the security context for all your files+folders?

$ semanage fcontext -l

What are the 2 steps to editing a file's SELinux context?

1. First update the target policy itself
2. Then you apply the updated policy to your files and folders.

What is the command to view the semanage command's subcommands?

$ semanage -help

What is the command, to view each of these subcommand's man pages?

$ man semanage-{subcommand}

Which subcommand is used for editing the SELinux file mapping definition?


What is the command to view this command's man page?

$ man semanage-fcontext

What is the command to view the fcontext subcommand's help info?

$ semanage fcontext -help

Where can you find examples commands for editing a file's targeted policy?

$ man semanage-fcontext

What is the command to apply the updated policy to the file /tmp/testfile.txt?

$ restorecon /tmp/testfile.txt

How do you refresh all files and folders contexts across the whole machine?

$ touch /.autorelabel
# then reboot the machine.

When you create a new file or folder, then SELinux will automatically assign a value to it. The semanage fcontext -l command gives info about how SELinux determines what security context it needs to assign to all your machine’s files and folders:

$ semanage fcontext -l | wc -l
$ semanage fcontext -l
/etc/cron\.(daily|weekly)/sysklogd    regular file       system_u:object_r:logrotate_exec_t:s0
/etc/cron\.d(/.*)?                    all files          system_u:object_r:system_cron_spool_t:s0
/etc/cron\.daily/[sm]locate           regular file       system_u:object_r:locate_exec_t:s0
/etc/cron\.daily/calamaris            regular file       system_u:object_r:calamaris_exec_t:s0
/etc/cron\.daily/certwatch            regular file       system_u:object_r:certwatch_exec_t:s0
/etc/cron\.daily/prelink              regular file       system_u:object_r:prelink_cron_system_exec_t:s0
/etc/cron\.monthly/proftpd            regular file       system_u:object_r:ftpd_exec_t:s0
/etc/cron\.weekly/(c)?fingerd         regular file       system_u:object_r:fingerd_exec_t:s0
/etc/crontab                          regular file       system_u:object_r:system_cron_spool_t:s0
/etc/ctdb/events\.d/.*                regular file       system_u:object_r:bin_t:s0
/etc/cups(/.*)?                       all files          system_u:object_r:cupsd_etc_t:s0
/etc/cups/certs                       directory          system_u:object_r:cupsd_rw_etc_t:s0
/etc/cups/certs/.*                    regular file       system_u:object_r:cupsd_rw_etc_t:s0
/etc/cups/classes\.conf.*             regular file       system_u:object_r:cupsd_rw_etc_t:s0
/etc/cups/client\.conf                regular file       system_u:object_r:etc_t:s0

Note, the “(/.*)?” means any child elements will inherit the items security context automatically.

This command essentially gives the definitive info about what SELinux context every single file and folder must have on your machine. The semanage command retrieves info from the particular policy type that’s currently active (which is usually the targeted policy type).

However when you install an rpm package, the rpm in most cases assign security attribute values to all it’s objects, but for those it doesn’t the policy type will take over. In most cases the given objects values are assigned based on inheritance. E.g. when a user starts a new process, then that new process inherits the user’s security attributes, or if a file is created, then that file inherits of the attributes of the folder it resides in.

Edit a file’s security context using Semanage

Now if you want a file/folder to have a different security context than what’s defined by semanage fcontext -l, then the best way to do this is to first modify the targeted policy itself (using the semanage command). This will mean your changes become part of the source information and hence will survive a reboot (or even a relabel, covered later). After that targeted policy is updated, the next part is to apply the new/updated policy rule to the file/folder. To summarise:

  1. First update the target policy itself
  2. Then you apply the updated policy to your files and folders.

Before we show how you edit one of the targeted policies listed in semanage fcontext -l, let’s first explore semanage itself because it is a really powerful and feature rich command. Here’s the help info for the semanage command:

semanage -h
usage: semanage [-h]


semanage is used to configure certain elements of SELinux policy with-out
requiring modification to or recompilation from policy source.

positional arguments:
    import              Output local customizations
    export              Output local customizations
    login               Manage login mappings between linux users and SELinux
                        confined users
    user                Manage SELinux confined users (Roles and levels for an
                        SELinux user)
    port                Manage network port type definitions
    interface           Manage network interface type definitions
    module              Manage SELinux policy modules
    node                Manage network node type definitions
    fcontext            Manage file context mapping definitions
    boolean             Manage booleans to selectively enable functionality
    permissive          Manage process type enforcement mode
    dontaudit           Disable/Enable dontaudit rules in policy

optional arguments:
  -h, --help            show this help message and exit

As you can see, semanage has about a dozen sub commands. Each subcommand has it’s own man page, which you can access like this:

$ man semanage-{subcommand}


$ man semanage-fcontext

In our case we are interested in the fcontext subcommand:

$ semanage fcontext -h
usage: semanage fcontext [-h] [-n] [-N] [-S STORE] [ --add ( -t TYPE -f FTYPE -r RANGE -s SEUSER | -e EQUAL ) FILE_SPEC ) | --delete ( -t TYPE -f FTYPE | -e EQUAL ) FILE_SPEC ) | --deleteall  | --extract  | --list -C | --modify ( -t TYPE -f FTYPE -r RANGE -s SEUSER | -e EQUAL ) FILE_SPEC ) ]

positional arguments:
  file_spec             file_spec

optional arguments:
  -h, --help            show this help message and exit
  -C, --locallist       List fcontext local customizations
  -n, --noheading       Do not print heading when listing fcontext object
  -N, --noreload        Do not reload policy after commit
  -S STORE, --store STORE
                        Select an alternate SELinux Policy Store to manage
  -a, --add             Add a record of the fcontext object type
  -d, --delete          Delete a record of the fcontext object type
  -m, --modify          Modify a record of the fcontext object type
  -l, --list            List records of the fcontext object type
  -E, --extract         Extract customizable commands, for use within a
  -D, --deleteall       Remove all fcontext objects local customizations
  -e EQUAL, --equal EQUAL
                        Substitute target path with sourcepath when generating
                        default label. This is used with fcontext. Requires
                        source and target path arguments. The context labeling
                        for the target subtree is made equivalent to that
                        defined for the source.
  -f {a,f,d,c,b,s,l,p}, --ftype {a,f,d,c,b,s,l,p}
                        File Type. This is used with fcontext. Requires a file
                        type as shown in the mode field by ls, e.g. use -d to
                        match only directories or -- to match only regular
                        files. The following file type options can be passed:
                        -- (regular file),-d (directory),-c (character
                        device), -b (block device),-s (socket),-l (symbolic
                        link),-p (named pipe) If you do not specify a file
                        type, the file type will default to "all files".
  -s SEUSER, --seuser SEUSER
                        SELinux user name
  -t TYPE, --type TYPE  SELinux Type for the object
  -r RANGE, --range RANGE
                        MLS/MCS Security Range (MLS/MCS Systems only) SELinux
                        Range for SELinux login mapping defaults to the
                        SELinux user record range.

This indicates that we can add/modify/delete the targeted policies with semanage’s fcontext sub command.

The semanage fcontext’s man page actually contains examples on how to do this:

$ man semanage-fcontext | grep -A16 "EXAMPLE"
       remember to run restorecon after you set the file context
       Add file-context for everything under /web
       # semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
       # restorecon -R -v /web

       Substitute /home1 with /home when setting file context
       # semanage fcontext -a -e /home /home1
       # restorecon -R -v /home1

       For home directories under top level directory, for example /disk6/home,
       execute the following commands.
       # semanage fcontext -a -t home_root_t "/disk6"
       # semanage fcontext -a -e /home /disk6/home
       # restorecon -R -v /disk6

Now lets try this out, first let’s create a file:

$ touch /var/www/html/hello.html
$ ls -lZ /var/www/html/hello.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/hello.html

Now let’s say we want to change the type security attribute to “admin_home_t”, then based on the man page’s example, we do:

$ semanage fcontext -a -t admin_home_t /var/www/html/hello.html

So now we have added a new targets policy to the fcontext catalog:

$ semanage fcontext -l | grep hello.html
/var/www/html/hello.html       all files          system_u:object_r:admin_home_t:s0

Now to apply this policy rule to the file, we need to use the restorecon command:

$ ls -lZ /var/www/html/hello.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/hello.html
$ restorecon /var/www/html/hello.html
$ ls -lZ /var/www/html/hello.html
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /var/www/html/hello.html

the restorecon command essentially sets the security context for a file/folder based on the rules specified by semanage fcontext -l command.

In the above example, we applied the “restorecon” command to only one file. However if you want to run the restorecon command on every single file on your machine, then you can do this by simply creating the following file empty file:

$ touch /.autorelabel
$ ls -la / | grep '.autorelabel'
-rw-r--r--.   1 root    root       0 Oct 13 20:02 .autorelabel

After this file has been created, you simply reboot the machine for the autorelabel to start. This can be quite time consuming and as result your machine’s reboot may take several minutes longer then it usually does. Once the relabelling is complete, the .autorelabel file is automatically deleted.

Note, creating this /.autorelabel null file is something we need to do when we don’t know what the root password is and therefore we perform a password reset.

An alternative way to doing a complete machine level restorecon is by doing changing the default SELinux mode to disabled and then switching the default back to either permissive of enabled again. This approach will require you do 2 machine reboots instead of one.

A common example of why you need to create your own targeted policies

By default httpd will use the /var/www as the Documetroot. However you might want to change this default to a new custom folder, e.g.:

$ mkdir /webcontent
$ echo "hello world" > /webcontent/index.html
$ chown -R apache:apache /webcontent

You would then update the httpd config file to point to this new “DocumentRoot” folder.

Now ensure that selinux mode is set to enabled:

$ setenforce Enforcing
$ getenforce

Now if you open up your servers homepage in a web browser you will find that you get an error message. That’s because the security context of the /webcontent folder and it’s children is wrong:

$ ls -laZ /webcontent
drwxr-xr-x. apache apache unconfined_u:object_r:default_t:s0 .
dr-xr-xr-x. root   root   system_u:object_r:root_t:s0      ..
-rw-r--r--. apache apache unconfined_u:object_r:default_t:s0 index.html

That’s because $ semanage fcontext -l doesn’t contain any specific policies for our custom made folder:

$ semanage fcontext -l | grep webcontent

Therefore our folder and it’s children just got a context with the generic type “default_t”.

However for the apache process to be able to access /webcontent folder and it’s contents, there security context needs to be the same as that of the original default DocumentRoot folder:

$ ls -laZ /var | grep www
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 www

By reviewing the examples in the semanage-fcontext man page, we found that we need to run the following command to define our new security context for the /webcontent folder and it’s children:

$ semanage fcontext -l | grep webcontent
$ semanage fcontext -a -t httpd_sys_content_t "/webcontent(/.*)?"

Now let’s confirm this policy has been added to the catalog:

$ semanage fcontext -l | grep webcontent
/webcontent(/.*)?         all files          system_u:object_r:httpd_sys_content_t:s0

Finally we can now apply this policy to our folder and it’s children.

First let’s check again what it is currently:

$ ls -laZ /webcontent
drwxr-xr-x. apache apache unconfined_u:object_r:default_t:s0 .
dr-xr-xr-x. root   root   system_u:object_r:root_t:s0      ..
-rw-r--r--. apache apache unconfined_u:object_r:default_t:s0 index.html

Now apply our new policy to the /webcontent folder and it’s children:

$ restorecon -r /webcontent

Now let’s check again:

$ ls -laZ /webcontent
drwxr-xr-x. apache apache unconfined_u:object_r:httpd_sys_content_t:s0 .
dr-xr-xr-x. root   root   system_u:object_r:root_t:s0      ..
-rw-r--r--. apache apache unconfined_u:object_r:httpd_sys_content_t:s0 index.html

We should now be able to access the index.html via a web browser.