Zatoichi's Engineering Blog

Musings from a firmware engineer

AppArmor and Its Performance Impact

14 Nov 2017

Mandatory Access Control

Traditional UNIX based systems restrict what resources different users can access by means of labeling resources so only a given user or group can access them. Controls are discretionary because a given user may be capable of passing a permission (directly or indirectly) to another user. An example would be creating a file then marking its permissions readable by other users. Such a control scheme is referred to as Discretionary Access Control (DAC).

An alternative to DAC is Mandatory Access Control (MAC). A MAC system can further constrain what a system can do, and is based on a policy. Restrictions can be imposed on users, process, and threads, and can involve resources ranging from file and directories to TCP/UDP ports, shared memory segments, and I/O devices. When an action is attempted the kernel will examine the current policy and determine if the action is allowed or not.

In 2001 the development of a reference monitor in the Linux kernel started, and the result is the Linux Security Modules (LSM) framework. Using this framework anyone could create a Linux kernel module which enforced a given MAC. The LSM consists of a number of hooks which can be used to determine if certain actions should proceed or should be blocked.

Several MAC implementations have been developed on top of LSM, and these include SELinux, AppArmor, Smack, and TOMOYO Linux. Each of these has its goals and capabilities. This post focuses on AppArmor.

AppArmor is a MAC which allows a system to restrict the actions of individual programs, regardless of what user executes them. Each program which is restricted has a profile which defines what it is allowed to do. Profiles can restrict capabilities (typically available to root), network access, and file system access. AppArmor is not appropriate for locking down every application in a system, but could be used to restrict the behavior of certain applications, especially those which are accessible over the network or handle untrusted data.

Analyzing AppArmor

AppArmor was analyzed to determine its performance impact on a system, both when it is enabled with no profiles and when a profile was active. To facilitate the analysis, a custom Linux distribution was built using Yocto, one build with AppArmor enabled in the kernel and one without. Yocto version Rocko was used, which includes Linux version v4.12. The build was run on QEMU and analyzed. See this post on how to create a custom QEMU image, in my case on macOS.

The Yocto build was a bare-bones build with two exceptions: FFmpeg was included which will be used to compare performance, and AppArmor’s tools were included. Adding these two were accomplished by adding the following to the conf/local.conf file in the build directory:

# Add ffmpeg and allow its commercial license flag
CORE_IMAGE_EXTRA_INSTALL += "ffmpeg"
LICENSE_FLAGS_WHITELIST += "commercial"
# Add AppArmor's tools
CORE_IMAGE_EXTRA_INSTALL += "apparmor"

# Add extra space (in KB) to the file system, so that the
# benchmark has space to output its file(s).
IMAGE_ROOTFS_EXTRA_SPACE = "512000"

The AppArmor tools required the following BB layers in the conf/bblayers.conf file:

BBLAYERS ?= " \
  /workdir/poky/meta \
  /workdir/poky/meta-poky \
  /workdir/openembedded-core/meta \
  /workdir/meta-security \
  /workdir/meta-openembedded/meta-oe \
  /workdir/meta-openembedded/meta-perl \
  /workdir/meta-openembedded/meta-networking \
  /workdir/meta-openembedded/meta-python \
  /workdir/poky/meta-yocto-bsp \
  "

In addition a dependency needed to be removed from the apparmor recipe, as the AppArmor tests were failing due to a missing dependency:

diff --git a/recipes-security/AppArmor/apparmor_2.11.0.bb b/recipes-security/AppArmor/apparmor_2.11.0.bb
index a83c2c3..e1d5bb8 100644
--- a/recipes-security/AppArmor/apparmor_2.11.0.bb
+++ b/recipes-security/AppArmor/apparmor_2.11.0.bb
@@ -29,7 +29,7 @@ SRC_URI[sha256sum] = "b1c489ea11e7771b8e6b181532cafbf9ebe6603e3cb00e2558f21b7a5b"

 PARALLEL_MAKE = ""

-inherit pkgconfig autotools-brokensep update-rc.d python3native perlnative ptest cpan
+inherit pkgconfig autotools-brokensep update-rc.d python3native perlnative cpan
 inherit ${@bb.utils.contains('VIRTUAL-RUNTIME_init_manager','systemd','systemd','', d)}

 S = "${WORKDIR}/apparmor-${PV}"

Performance cost

Enabling the AppArmor LSM should involve some overhead as different operations are checked against the given policy. However, the question is can the performance cost be measured or is it exceedingly small?

To quantify the performance impact, an experiment was conducted which encoded a small video 20 times in succession using FFmpeg. See this post for details on the experiment and the video file which was used. Three trials were conducted, one without AppArmor compiled into the kernel, one with it compiled and enabled but no profiles were enabled, and one where a simple FFmpeg profile was enabled. These three trials were designed to determine the impact of the kernel module alone as well as when a profile was active. The FFmpeg profile which was used in the third trial was as follows:

root@qemux86:~# cat /etc/apparmor.d/usr.bin.ffmpeg
#include <tunables/global>
/usr/bin/ffmpeg {
  #include <abstractions/base>

  /home/root/* rw,
}

The following three box plots show the results of the experiment (raw data here).

Boxplot

The results show that enabling the AppArmor kernel module does result in an increase of ~3.6 seconds on average, or 3%. The data appears to indicate that enabling the FFmpeg profile results in a further performance hit, but when the outlier is discarded the mean times are close, which may indicate that for a simple profile there it little additional performance impact.

Conclusion

The AppArmor LSM can be used to provide additional hardening to a system by enforcing Mandatory Access Controls on a per-application basis. There is a performance impact of enabling it in the kernel, however the impact may be worth the additional protection that it can provide.