How to add custom SELinux filename transition rules in RHEL7 and later

Solution Verified - Updated -

Environment

  • Red Hat Enterprise Linux 7
  • Red Hat Enterprise Linux 8
  • Red Hat Enterprise Linux 9

Issue

  • The Red Hat Enterprise Linux (RHEL) 7 SELinux User's and Administrator's Guide details a new file name transition feature and gives some policy examples but doesn't make it clear how a sysadmin could easily add a new rule. How can this be done?

  • An fcontext rule like the following makes it possible for restorecon to set /var/www/html/*/rwstorage files to the httpd_sys_rw_content_t type:

    semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html(/.*)?/rwstorage"
    

    However, the restorecon is always required, e.g.:

    ~]# mkdir -p /var/www/html/vhost1/rwstorage
    ~]# stat -c "%C  %n" /var/www/html/vhost1/{,rwstorage}
    unconfined_u:object_r:httpd_sys_content_t:s0  /var/www/html/vhost1/
    unconfined_u:object_r:httpd_sys_content_t:s0  /var/www/html/vhost1/rwstorage
    ~]# restorecon /var/www/html/vhost1/rwstorage
    ~]# stat -c "%C  %n" /var/www/html/vhost1/rwstorage
    unconfined_u:object_r:httpd_sys_rw_content_t:s0  /var/www/html/vhost1/rwstorage
    

    How can we make it so the manual restorecon isn't necessary in these situations? (And no we don't want to use the existing "/var/www/html(/.*)?/uploads" rule.)

Resolution

Using restorecond

  • Some situations can be easily handled by the restorecond service (provided by the policycoreutils-restorecond package from optional repository for RHEL 7 and BaseOS repository for RHEL 8/9).

    • restorecond allows for adding watch-paths to the lists in /etc/selinux/restorecond.conf and /etc/selinux/restorecond_user.conf
    • This doesn't solve all situations since the syntax only allows * in the last component of the target path (e.g., /root/.ssh/* is allowed but /var/www/html/*/rwstorage is not)

Using file name transition rules

  • See instructions outlined in this blog post by Red Hatter & SELinux guru Dan Walsh:
    New SELinux Feature: File Name Transitions

  • Alternatively, another Red Hatter wrote a unsupported script that automates the process:
    GitHub - ryran/b19scripts/add-file-trans-rule.sh
    For example:

    1. Download the script to a bin dir and make it executable

    2. Check the license and the help page

      [root@r72 ~]# grep '#  ' $(which add-file-trans-rule.sh)
      #    This program is free software: you can redistribute it and/or modify
      #    it under the terms of the GNU General Public License as published by
      #    the Free Software Foundation, either version 3 of the License, or
      #    (at your option) any later version.
      #    This program is distributed in the hope that it will be useful,
      #    but WITHOUT ANY WARRANTY; without even the implied warranty of
      #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      #    General Public License <gnu.org/licenses/gpl.html> for more details.
      
      [root@r72 ~]# add-file-trans-rule.sh -h
      Usage: add-file-trans-rule.sh <TARGET_FILE> <TARGET_FILE_CLASS>
      
      Where TARGET_FILE is the file to get auto-labeled without requiring restorecon.
      Where TARGET_FILE_CLASS is most likely "file" or "dir" but could be anything
      returned by "seinfo --class" command.
      
      Example:
      
      1. Add a rule to fcontext db first, e.g.:
      
        * semanage fcontext -a -t httpd_sys_rw_content_t \
            "/var/www/html(/.*)?/rwstoragedir"
      
        * semanage fcontext -a -t httpd_sys_rw_content_t \
            "/var/www/html/[^/]*/rwstoragefile"
      
      2. Then execute this script, e.g.:
      
          add-file-trans-rule.sh /var/www/html/vhost1/bak/rwstoragedir dir
          add-file-trans-rule.sh /var/www/html/vhost2/rwstoragefile file
      
      Note that by default this will set the source process domain to "unconfined_t",
      which is suitable for triggering on actions that normal unconfined users make.
      This can be overridden by changing the "PROCESS_DOMAIN" environment variable.
      
      Note that the script will prompt for a module name unless the environment
      variable "NEW_MODULE_NAME" is set. It will also prompt if "NEW_MODULE_NAME" is
      set to the name of a currently loaded module, as listed by "semodule -l".
      
    3. Create the desired fcontext rule and test that it works, e.g.:

      [root@r72 ~]# semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html(/.*)?/rwstorage"
      [root@r72 ~]# mkdir -p /var/www/html/vhost1/rwstorage
      [root@r72 ~]# stat -c %C /var/www/html/vhost1/rwstorage
      unconfined_u:object_r:httpd_sys_content_t:s0
      [root@r72 ~]# restorecon /var/www/html/vhost1/rwstorage
      [root@r72 ~]# stat -c %C /var/www/html/vhost1/rwstorage
      unconfined_u:object_r:httpd_sys_rw_content_t:s0
      
    4. Execute the script as directed, e.g.:

      [root@r72 ~]# add-file-trans-rule.sh /var/www/html/vhost1/rwstorage dir
      Missing packages
      Try: yum install selinux-policy-devel setools-console
      [root@r72 ~]# yum install selinux-policy-devel setools-console -y
      ...
      [root@r72 ~]# add-file-trans-rule.sh /var/www/html/vhost1/rwstorage dir
      Source process domain: "unconfined_t"
      Parent directory type: "httpd_sys_content_t"
      Target file: "rwstorage"
      Target class: "dir"
      
      About to create a file name transition policy module based on above specs.
      Cancel now if any of them are empty or incorrect.
      
      The new module will need a name.
      Names for loaded modules can be seen with the "semodule -l" command.
      Example: "my-filetrans-rwstorage"
      
      Enter a unique name for this new filetrans module:
      > my-filetrans-rwstorage
      Creating module files in tempdir: /tmp/tmp.addfiletrans.rwKR0U2CAI
      Executing: 'make -f /usr/share/selinux/devel/Makefile my-filetrans-rwstorage.pp'
      Compiling targeted my-filetrans-rwstorage module
      /usr/bin/checkmodule:  loading policy configuration from tmp/my-filetrans-rwstorage.tmp
      /usr/bin/checkmodule:  policy configuration loaded
      /usr/bin/checkmodule:  writing binary representation (version 17) to tmp/my-filetrans-rwstorage.mod
      Creating targeted my-filetrans-rwstorage.pp policy package
      rm tmp/my-filetrans-rwstorage.mod.fc tmp/my-filetrans-rwstorage.mod
      
      Assuming the above command finished without issue ...
      The final step requires you to manually install the module yourself
      Execute the following command:
      
        semodule -i /tmp/tmp.addfiletrans.rwKR0U2CAI/my-filetrans-rwstorage.pp
      
      After that you should see your module in "semodule -l"
      You can then disable it with "semodule -d my-filetrans-rwstorage"
      Or re-enable it with "semodule -e my-filetrans-rwstorage"
      You can also uninstall (remove) it with "semodule -r my-filetrans-rwstorage"
      
    5. Follow directions to install the module and confirm it works, e.g.:

      [root@r72 ~]# semodule -i /tmp/tmp.addfiletrans.rwKR0U2CAI/my-filetrans-rwstorage.pp
      [root@r72 ~]# rmdir /var/www/html/vhost1/rwstorage
      [root@r72 ~]# mkdir /var/www/html/vhost1/rwstorage
      [root@r72 ~]# stat -c %C /var/www/html/vhost1/rwstorage
      unconfined_u:object_r:httpd_sys_rw_content_t:s0
      
    6. Optionally disable and then re-enable it

      [root@r72 ~]# semodule --disable my-filetrans-rwstorage
      [root@r72 ~]# mkdir -p /var/www/html/vhost2/rwstorage
      [root@r72 ~]# stat -c %C /var/www/html/vhost2/rwstorage
      unconfined_u:object_r:httpd_sys_content_t:s0
      [root@r72 ~]# semodule --enable my-filetrans-rwstorage
      

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments