4 Managing Policies

For more information about policy rules and how they work, see About Policy Rules.

Listing Policy Rules

To list policy rules that are in use by fapolicyd, run:

sudo fapolicyd-cli -l

Output from this command might be similar to the following:

-> %languages=application/x-bytecode.ocaml,application/x-bytecode.python,application/java-archive,text/x-java,application/x-java-applet,application/javascript,text/javascript,text/x-awk,text/x-gawk,text/x-lisp,application/x-elc,text/x-lua,text/x-m4,text/x-nftables,text/x-perl,text/x-php,text/x-python,text/x-R,text/x-ruby,text/x-script.guile,text/x-tcl,text/x-luatex,text/x-systemtap
1. allow perm=any uid=0 : dir=/var/tmp/
2. allow perm=any uid=0 trust=1 : all
3. allow perm=open exe=/usr/bin/rpm : all
4. allow perm=open exe=/usr/bin/python3.9 comm=dnf : all
5. deny_audit perm=any pattern=ld_so : all
6. deny_audit perm=any all : ftype=application/x-bad-elf
7. allow perm=open all : ftype=application/x-sharedlib trust=1
8. deny_audit perm=open all : ftype=application/x-sharedlib
9. allow perm=execute all : trust=1
10. allow perm=open all : ftype=%languages trust=1
11. deny_audit perm=any all : ftype=%languages
12. allow perm=any all : ftype=text/x-shellscript
13. deny_audit perm=execute all : all
14. allow perm=open all : all

Note that the rules are numbered. When fapolicyd runs in debug mode, the output displays the rule number that's enforced for an event. You can use this information to decide whether you need to insert a new policy rule to change the existing policy and to decide where that rule might need to be in the policy hierarchy. See Debugging and Permissive Mode for information on debugging.

You can compare this list to the compiled rules to check whether you need to reload the rules into fapolicyd.

sudo cat /etc/fapolicyd/compiled.rules

See Checking and Loading Policy Rules.

Creating Policy Rules

You might need to create custom policy rules if the default policy is too restrictive and is preventing applications from running. You can also create custom policy rules to further restrict access to applications and files. Rules can be added to the /etc/fapolicyd/rules.d directory following the conventions described in About Policy Rules and in the fapolicyd.rules(5) manual page.

Rules have the following general format:

decision perm subject : object
  • decision: whether to allow or deny an event and whether to log that action. Values can be allow, deny, allow_audit, deny_audit, allow_syslog, deny_syslog, allow_log, or deny_log.
  • perm: the type of permission applied to the file, such as whether to trigger when the object is opened, run, or for any activity on the object. Values can be open, execute, or any. If no permission is specified, the default value is open.
  • subject: the actor performing the action on the object that the permission and decision applies to. This value can be set to all for every actor, but can also be limited to a particular UID or GID or another executable file. Values can be all, auid, uid, gid, sessionid, pid,ppid, trust, comm, exe, dir, device, pattern. See the fapolicyd.rules(5) manual page for more detail.
  • object: the files or applications that the decision applies to. This value can be specified in various ways, such as by providing the path to a particular file, the MIME type of the file or for file matches in the trust database. Values can be all, path, dir, device, ftype, trust, sha256hash. See the fapolicyd.rules(5) manual page for more detail.

You can specify several subject and object directives for a single rule. For example, you can match the file path, MIME type, and file size as the object for a rule.

Rules can also be created to generate macros, or sets, that consist of a key and a set of values in the form of integers or strings in a comma-separated list. Set rules are prefixed with the percentage (%) symbol, and the set can be referenced when creating a rule by specifying the key prefixed with the percentage (%) symbol. The format of a set rule follows:

%key=value1,value2

You can see an example of a set rule in /etc/fapolicyd/rules.d/10-languages.rules.

The following example rules can be used to help guide you when creating custom rules for an environment.

Example 4-1 Create a rule to allow a group of trusted users to run files matching the defined languages in their home directories

  1. Create a system group and add trusted users to that group, or select an existing group of trusted users. In this example, we use the adm group for system administrators.
  2. Create a policy rule file at /etc/fapolicyd/rules.d/50-adm-home-trust.rules and add the following content:
    allow perm=any gid=adm : ftype=%languages dir=/home
    deny_log perm=any all : ftype=%languages dir=/home
    Two rules are defined:
    • Grant all users in the group adm all permissions on any files, in the /home directory, of the type described in the languages set in /etc/fapolicyd/rules.d/10-languages.rules.
    • Deny all users any permissions on any files, in the /home directory, of the type described in the languages macro. The deny_log rule causes the event to be added to both the audit log and to the system log.
  3. Compile and load the new rules.
    sudo fagenrules --load

    See Checking and Loading Policy Rules for more information.

  4. Verify that the rule is in effect.
    1. As a user in the adm group, create a test executable file in $HOME/test_fapolicyd.py with the following content:

      #/usr/bin/python3
      print("Test succeeded")
    2. Set the file mode to executable:

      chmod +x $HOME/test_fapolicyd.py
    3. Run the file:
      $HOME/test_fapolicyd.py
      The following output is displayed:
      Test succeeded
    4. As a user that isn't in the adm group, repeat the same steps. When you run the test script, the following output is displayed:

      bash: ./test_fapolicyd.py: Operation not permitted
      If you have auditing configured, you can check for entries in the audit log as follows:
      sudo ausearch --start today -m fanotify
      Output similar to the following is displayed:
      ...
      time->Fri Jan  5 12:05:39 2024
      type=PROCTITLE msg=audit(1704456339.181:406): proctitle="bash"
      type=PATH msg=audit(1704456339.181:406): item=0 name="./test_fapolicyd.py" inode=68153551 
        dev=fc:00 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_home_t:s0 
        nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
      type=CWD msg=audit(1704456339.181:406): cwd="/home/guest"
      type=SYSCALL msg=audit(1704456339.181:406): arch=c000003e syscall=257 success=no exit=-1 
        a0=ffffff9c a1=555d4b74e050 a2=0 a3=0 items=1 ppid=46725 pid=46765 auid=1000 uid=1001 
        gid=1001 euid=1001 suid=1001 fsuid=1001 egid=1001 sgid=1001 fsgid=1001 tty=pts0 ses=3 
        comm="bash" exe="/usr/bin/bash" 
        subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
      type=FANOTIFY msg=audit(1704456339.181:406): resp=2

Example 4-2 Create a rule to allow users to run a trusted application

Note that creating rules to allow particular applications to run is less efficient than adding the application to the trust database. See Adding Files to the Trust File Database for more information. Only add rules for specific files if you need to provide more explicit controls over file accesses. In this example, a rule is created controlling the ability to run a particular binary application that can only be run by using the trusted bash shell binary.

  1. Create a policy rule file at /etc/fapolicyd/rules.d/80-trustapp.rules and add the following content:
    allow_log perm=execute exe=/usr/bin/bash trust=1 : path=/opt/external/app.bin ftype=application/x-executable trust=0

    The rule states that in the case that the trusted bash shell tries to run the untrusted application at the path /opt/external/app.bin, where that file is of MIME type application/x-executable, the action is allowed. Note that the decision is set to allow_log so that the action is logged for when we verify that the rule is working. After you have verified the rule, you can change the decision to allow.

    Tip:

    To check the mime type of a file when writing rules, run the following command: fapolicyd-cli --ftype /path-to-file

    Note that by specifying the MIME type for the file and the way in which the file can be loaded, the rule is reasonably restrictive. You can optionally create a more restrictive rule based on the SHA-256 hash of the file, which would prevent the rule from applying if the file is modified:

    • Obtain the SHA-256 hash for the file.
      sha256sum /opt/external/app.bin|awk '{print $1}'
    • Use the SHA-256 hash to rewrite the rule as follows:
      allow perm=execute exe=/usr/bin/bash trust=1 : sha256hash=340e...74f3cdd3babb

      Set the value of sha256hash to the value that you obtained from running the previous command.

  2. Compile and load the new rules.
    sudo fagenrules --load

    See Checking and Loading Policy Rules for more information.

  3. Verify that the rule is in effect.
    When you try to run /opt/external/app.bin as a standard user from the Bash shell, it runs correctly. Because the decision in the rule is to allow_log, you can view the fapolicyd log to see the rule in action. For example, run:
    sudo journalctl -S today -u fapolicyd|tail

    The output displays that the rule is being enforced, for example:

    Jan 05 14:22:36 ro-ansible-ol8 fapolicyd[45792]: rule=13 dec=allow_log 
      perm=execute auid=1000 pid=50439 exe=/usr/bin/bash : path=/opt/app.bin 
      ftype=application/x-executable trust=0

Checking and Loading Policy Rules

If rules have been added or changed, you must check for consistency with the compiled rule set that fapolicyd uses and load them into fapolicyd.

  1. Check for inconsistencies between the rules in /etc/fapolicyd/rules.d and the compiled rules in /etc/fapolicyd/compiled.rules.
    sudo fagenrules --check

    If the rules in /etc/fapolicyd/rules.d have been updated and need to be recompiled and loaded, the output appears as follows:

    /sbin/fagenrules: Rules have changed and should be updated
  2. To compile the rules in /etc/fapolicyd/rules.d and load them into fapolicyd, run:
    sudo fagenrules --load

    You don't need to restart fapolicyd for the changes to take effect.

  3. List the rules to review that the changes have loaded correctly into fapolicyd.
    sudo fapolicyd-cli  -l

Changing Default Policy Logging

Default policy rules shipped with fapolicyd are configured to only log to the audit log for denials. This configuration is appropriate for production systems but the information stored in these logs might be limited for debugging purposes. If you need to track which rules are being used to make the final decision on an event, you can either run fapolicyd in debugging mode, or you could change rules to output information to the system log. For more information on running fapolicyd in debugging mode, see Debugging and Permissive Mode.

Policy rule decisions identify whether to log information and how that information must be logged. By default, for denial decisions, the rules that are included in the fapolicyd package use the deny_audit decision type. You can change all deny_audit decision type to deny_log to log information to both the audit log and to the system log.

To enhance logging:

  1. Update all rules in /etc/fapolicyd/rules.d to replace deny_audit with deny_log.
    sudo bash -c 'for i in /etc/fapolicyd/rules.d/*; do sed -i "s/deny_audit/deny_log/g" $i; done'

    You can also enable logging for any allow rules, but doing so can result in verbose output and can have significant performance impact.

  2. Check that the rules are updated.
    sudo fagenrules --check
  3. Load the new rules.
    sudo fagenrules --load
  4. Review the rules to ensure that the change has loaded correctly into fapolicyd.
    sudo fapolicyd-cli  -l | grep 'deny_log'

When an event is denied by fapolicyd and the decision is set to deny_log, an entry appears in the system log, similar to the following:

fapolicyd[1478]: rule=13 dec=deny_log perm=execute auid=1000 pid=5361 exe=/usr/bin/bash : 
   path=/home/user/demo.bin ftype=application/x-executable trust=0

Note that the output includes the rule number for the rule that fapolicyd used to make the final decision to deny the event.

To view system log entries for fapolicyd, run:

sudo journalctl -S today -u fapolicyd