1 About the File Access Policy Daemon

The File Access Policy Daemon, fapolicyd, is a service that can be used to help protect a system by limiting which applications have permission to run. The service can be used to complement other security related services, including SELinux. Unlike SELinux, which isn't concerned with how files and applications are installed onto the system and whether they're trusted, fapolicyd implements policy decisions based on whether applications are trusted and how they were installed onto the system.

Fapolicyd uses the fanotify kernel API to monitor file system events. When a file is accessed, fapolicyd decides whether the event can continue by checking the file against a trust database and evaluating a set of policy rules. If the file isn't in the trust database and a policy rule denies the action, the event is blocked and an EACCESS 'Permission denied' error is returned to the user.

Fapolicyd automatically adds files that are installed by DNF to the trust database, by using a DNF plugin. This approach helps to make fapolicyd more efficient when evaluating files that have been installed legitimately onto the system. Files can be evaluated based on their SHA-256 hash so that they can't be modified after they're added to the trust database. You can optionally add files to the trust database for files that aren't installed by DNF. You must reload the database after files are added manually or when files are installed by using the rpm command outside of the DNF framework.

A cache is used by Fapolicyd to help improve performance and to reduce the amount of time spent processing rules and performing database lookups for frequent events.

Fapolicyd rules define logging options that can be used to audit events. The default policy uses the audit log which can be viewed by using the ausearch command. You can change policy rules to log to the system log or to both the audit log and the system log to help with debugging.

For more information about the Fapolicyd see https://github.com/linux-application-whitelisting/fapolicyd.

About the Trust Database

Fapolicyd uses a trust database to efficiently lookup files that are trusted by the system. If a file isn't in the trust database, fapolicyd falls back to processing policy rules to decide whether an event is allowed or not.

The trust database is partitioned into information that fapolicyd gathers about installed RPM packages and information added manually by using configuration files.

The trust database is automatically populated with information about files that are installed onto the system, by copying information from the RPM database. When fapolicyd is started or an update is run, the trust database is updated for all files listed in the RPM database. The trust database is also updated automatically when new packages are installed or packages are updated by using DNF. The tracking of package data is handled by the fapolicyd-dnf-plugin, which notifies the fapolicyd daemon about DNF updates or installations.

If you install packages directly by using the rpm command, then the fapolicyd RPM database isn't updated and you might experience system freezes. In this case, it can be useful to refresh the trust database. See Refreshing the Trust Database for more information.

Administrators can also add files to the trust database manually when files are installed or added to the system outside of the usual DNF and RPM packaging mechanisms, such as compiling binaries from source, or when using the Python pip utility, Ruby's gem utility, Node.js's npm utility, or Perl's CPAN tooling.

The trust database distinguishes between these two types of trust: files that are trusted because they belong to the RPM database, and files that are trusted because they have been added manually to the trust database. For example, entries that are trusted from the RPM database are of the type rpmdb:

rpmdb /usr/bin/dnf-3 2092 0a53d05260ba7ed4573...7ec64816e3ad49a2078c84836aeb7833e

Files that are added manually to the trust database are of the type filedb, for example:

filedb /home/user/demo.bin 140468 e38cd120c925...46c9cd1aa83e44e697f0f3393d98b305

The database also stores the path to the file, the size of the file in bytes and a SHA-256 hash for the file. The file size and SHA-256 hash can be used to perform further integrity checks on files to make the system much more restrictive and robust against malicious activity. Although enabling integrity checking can protect against somebody working around fapolicyd by changing a file at a particular location, we don't recommend configuring fapolicyd for integrity checking because it increases the risk of system deadlock. Integrity checks are disabled in fapolicyd by default. See Checking for Trust Mismatches and Viewing the Content in the Trust Database for more information.

Note that processing of trusted files in the trust database is cached and is much quicker than the processing of individual policy rules. Therefore, if you need fapolicyd to trust particular applications or files that are made available to the system outside of DNF, it's more efficient to add them to the trust file database than to define rules for them. Only add policy rules for individual files if you need custom rules around user or group permissions.

About Policy Rules

Policy rules control how fapolicyd handles files that aren't explicitly listed within the trust database. Policy rules can also be used to further restrict behavior on the system for files that are in the trust database. You can use policy rules to make fapolicyd more or less restrictive. You can define policy rules to create exceptions that allow or deny certain applications for specified scenarios. For example, you can create rules to explicitly allow an application for a particular user or group, but to deny the application for all other users.

The fapolicyd package ships with two policy rule sets:
  • The known-libs policy

    The known-libs policy is the default rule set and is designed to protect the system by only allowing known applications or libraries to run. The policy is slightly more permissive because it allows Elf binaries, python programs, and shell scripts to run for trusted applications and libraries.

  • The restrictive policy

    The restrictive policy provides mostly the same rules as the known-libs policy, but includes several more restrictive rules that prevent the running of any application or library that's not within the trust database. This policy blocks any possibility of running any executable file that isn't trusted.

The rules for these policies are shipped in /usr/share/fapolicyd/sample-rules/. The rules that apply to the known-libs policy are copied into /etc/fapolicyd/rules.d/ when the package is installed to make them active. The files that apply to each policy are described in /usr/share/fapolicyd/sample-rules/README-rules.

Fapolicyd processes rules based on their natural sort order, so rule files are named according to the following prefix convention:

  • 10-: Definitions of macros that can be used in other rules.
  • 20-: Rules to work around fapolicyd for system critical activity, such as when dracut builds kernel initramfs files or when DNF needs to run particular tools for updates.
  • 30-: Rules that identify access patterns that show how a program might be started. A default rule checks for programs that are started by the runtime linker (ld.so).
  • 40-: Rules for ELF binary files, such as rules to prevent malformed ELF files from running even if trusted, trust rules for ELF libraries and for trusted ELF binary executable files.
  • 50-: Rules that set out which users or groups are trusted to run particular programs or access particular files.
  • 60-: Rules for access to particular applications, where the application isn't in the trust database.
  • 70-: Rules related to different programming languages or scripting languages, such as Python, Perl, PHP, Ruby, or Lua.
  • 80-: Rules for trusted applications that might need advanced access controls.
  • 90-: General catch-all allow and deny rules.

Rules are compiled into a single file in /etc/fapolicyd/compiled.rules that fapolicyd reads at runtime.

Rule structure is described in detail in the fapolicyd.rules(5) manual page.