AppArmor is a Linux kernel module that implements Mandatory Access Control (MAC) policies through the Linux Security Modules (LSM) framework. It is similar to SELinux in that it provides a kernel-enforced mechanism to restrict application behavior, except that it primarily uses filesystem paths rather than inodes and labels in order to apply restrictions to running processes. Support for AppArmor must be compiled into the running Linux kernel in order for AppArmor restrictions to be enforced.
Stock Linux kernels since version 2.6.36 already ship with AppArmor support, however this support is removed in the kernels built and shipped by certain distributions, notably the ARM builds of Raspbian. (See § Enabling AppArmor on a Raspberry Pi for instructions to re-enable AppArmor support on Raspberry Pi hardware.) Popular Debian-based operating system distributions such as Ubuntu ship with AppArmor enabled by default. (Contrast with distributions such as CentOS that enable SELinux but not AppArmor by default.)
- 1 Installing AppArmor utilities
- 2 Checking for AppArmor support
- 3 Enabling AppArmor
- 3.1 Enabling AppArmor via GRUB
- 3.2 Enabling AppArmor on a Raspberry Pi
- 4 Installing AppArmor profiles
- 5 AppArmor profile directory structure
- 6 See also
Installing AppArmor utilities¶
To interact with AppArmor, you will need to install several userland utilties. On a Debian-based distribution, these are provided in the
apparmor-utils package. Install it with:
sudo apt update && sudo apt install apparmor-utils
Checking for AppArmor support¶
aa-status utility (or
apparmor_status, which is often a symbolic link to the
aa-status binary) is a userland program that reports the status of AppArmor on the current system. On a system where AppArmor is supported in the kernel, the first line of output from this utility will read:
apparmor module is loaded.
If AppArmor is supported by your kernel but is not enabled, the second line of output from
aa-status will read:
apparmor filesystem is not mounted.
In this case, you will need to enable AppArmor.
For a more granular assement, use the
aa-enabled utility to check whether AppArmor is enabled. This utility reports the reason why AppArmor may not be enabled as its error code. See the
aa-enabled(1) manual page for more information.
If your kernel supports AppArmor but it is not active, you must enable AppArmor in order to benefit from it. This situation most often occurs when the kernel supports AppArmor but is not configured to enable it by default. In this situation, AppArmor support must be explicitly enabled by instructing the bootloader to pass recognized command line parameters to the kernel upon its initialization.
In a typical configuration, the command line parameters are:
apparmor=1: This enables the AppArmor kernel module.
security=apparmor: This selects the AppArmor kernel module to be the currently enforcing Linux Security Module security model.
Enabling AppArmor via GRUB¶
If your system uses GNU GRUB as its bootloader, you can pass command line arguments to the kernel during the boot sequence.
Enabling AppArmor via GRUB for a single boot¶
To enable AppArmor for a single boot:
- Restart your computer.
- When the GRUB menu appears, press the
ekey to edit the currently selected entry.
- Find the kernel command line (the line that starts with
linux), and append
apparmor=1 security=apparmorto the end of it.
- Press the
ESCkey or the
CTRL-xkey combination to boot the system with the edited command line.
Enabling AppArmor for every boot¶
- Edit the
/etc/default/grubfile by appending
apparmor=1 security=apparmorto the
sudo update-grub. This will rewrite your
/boot/grub/grub.cfgfile so that, when GRUB loads, it will include the AppArmor kernel command line parameters as part of the boot menu entries.
- Restart the system.
Enabling AppArmor on a Raspberry Pi¶
By default, the Raspberry Pi Foundation does not enable AppArmor in the Linux kernels of their Raspbian OS distributions for the Raspberry Pi single board computers due to performance overheard concerns. The impact that AppArmor has on a Raspberry Pi’s performance is not hugely significant, but is non-negligible. Moreover, relatively few users are aware of AppArmor’s benefits and only a handful of packages ship with developer-supplied AppArmor profiles. Unless these factors change, the Raspberry Pi Foundation’s evaluation is that AppArmor is not a great enough boon to Raspberry Pi users to enable it by default.
If an AppArmor profile is available for the software you wish to constrain, however, enabling AppArmor may prove worthwhile. An example of software whose developers provide an AppArmor profile is Tor. Enabling AppArmor may also prove worthwhile if you write your own AppArmor profile for a given process.
This section provides guidance for configuring, recompiling, and installing a custom Raspberry Pi kernel with AppArmor support enabled. It is largely based on the official Raspberry Pi documentation for building and configuring a custom kernel along with information gathered from Raspberry Pi support forum postings.
Cross-compiling the RPi kernel¶
While it is possible to build a new kernel directly on Raspberry Pi hardware itself, doing so takes significantly longer. This section describes the process of cross-compiling the Raspberry Pi’s Linux kernel on an Intel x86-compatible chipset. The instructions make use of a Vagrant-managed and VirtualBox-backed virtual machine running a 64-bit version of the Ubuntu operating system as the build environment. Ubuntu is chosen for its similarities to the Raspberry Pi’s own environment.
- Install VirtualBox.
- Install Vagrant.
- Define an Ubuntu virtual machine using Vagrant:
mkdir rpi-kernel-build # Make a new directory to house the VM. cd rpi-kernel-build # Go to that directory. vagrant init -m ubuntu/bionic64 # Write a Vagrantfile configuration.
- Boot the virtual machine:
- Enter the virtual machine over SSH:
- Ensure the necessary build tools are installed. These include the
gitsource code management (SCM) system and the
sudo apt install git bc
- Next, download the kernel source code from the Raspberry Pi Foundation’s fork of the upstream Linux kernel. We’ll be doing this in the special
/vagrantdirectory which is automatically synchronized between the guest virtual machine and the host physical machine.
cd /vagrant # We have no need for downloading development history, so we # pass the `--depth 1` argument to `git clone`, which saves a # lot of disk space and bandwidth. git clone --depth 1 https://github.com/raspberrypi/linux
- Next, download the cross-compiling toolchain so that we can produce ARM-compatible machine code despite building on an Intel x86-based machine:
git clone --depth 1 https://github.com/raspberrypi/tools
- Add the cross-compilation toolchain utilities to your shell’s executable search
PATHvariable so that the tools can be invoked by the build scripts:
- Change into the
linuxsource code directory:
- Write the initial version of the (basic, default)
.configkernel configuration file using the Raspberry Pi Foundation’s makefile targets:
- If you are building a kernel for the Pi 1, Pi Zero, Pi Zero W, or Compute Module (earlier than version 3) hardware models:
# Invoke the `bcmrpi_defconfig` make target to create your `.config` file. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig
- If you are building a kernel for the Pi 2, Pi 3, Pi 3+, or Compute Module 3 hardware models:
# Invoke the `bcm2709_defconfig` make target to create your `.config` file. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
- If you are building a kernel for the Pi 1, Pi Zero, Pi Zero W, or Compute Module (earlier than version 3) hardware models:
- Customize your
.configfile by using a configuration tool such as menuconfig (i.e., install the menuconfig dependencies,
sudo apt install libncurses5-dev, and then invoke
make menuconfigto start the configuration process) or by editing the
.configfile directly with a text editor (e.g.,
vim .config) so that it includes support for the AppArmor module. Doing so requires the following lines to be present and in your
CONFIG_SECURITY=y CONFIG_SECURITYFS=y CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_PATH=y CONFIG_SECURITY_APPARMOR=y CONFIG_SECURITY_APPARMOR_HASH=y CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 CONFIG_INTEGRITY=y CONFIG_INTEGRITY_AUDIT=y CONFIG_DEFAULT_SECURITY_APPARMOR=y CONFIG_DEFAULT_SECURITY="apparmor" CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y CONFIG_AUDIT_WATCH=y CONFIG_AUDIT_TREE=y CONFIG_CRYPTO_SHA1=y CONFIG_AUDIT_GENERIC=y # CONFIG_DEFAULT_SECURITY_DAC is not set
- Compile the configured kernel (
zImage), kernel modules (
modules), and device tree blobs (
dtbs) by invoking
makewith their targets through the cross-compilation toolchain:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs
- Next, build and write out (“install”) the kernel module directory hierarchy for the new kernel. This will create a
$KERNEL_VERSIONis the version of the newly built kernel) at the
$INSTALL_MOD_PATHlocation (the special
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/vagrant modules_install
In this current directory, you should now have a new kernel with support for AppArmor (in the file named
zImage), numerous device tree binary blobs (in the files that end with the
overlaysdirectory containing device tree overlay object files. In the
/vagrant), you will have a
lib/directory containing a
modules/directory containing the kernel modules for the built kernel.
- The kernel and device tree blob and overlay files, and probably the kernel modules as well, will need to be copied to the hard disk (i.e., the SD card) from which the Raspberry Pi will boot. This can be accomplished over a network connection with the use of, for example,
scp(1)while the Raspberry Pi is running or directly onto the disk itself by removing the SD card from the Pi and making the disk’s filesystem available to your build computer through a USB port. Either way, the following table shows which file generated from the cross-compilation process should end up in which filesystem location on the Raspbery Pi’s SD card:
|Built file or directory tree||Ultimate destination on Raspberry Pi||Notes|
|| For Pi 1, Pi Zero, Pi Zero W, or Compute Module (earlier than version 3) hardware models, the default kernel image file is
After copying the built files to their correct ultimate destinations as mapped in the table above, you should be able to reboot the Raspberry Pi, invoke the
aa-status utility, and see that the AppArmor module is loaded into the running kernel as described in § Checking for AppArmor support. The next step is to begin § Installing AppArmor profiles
Building a new kernel on RPi hardware¶
Building with Ansible¶
The AnarchoTech NYC collective provides an AppArmor-enabled Linux kernel for the Raspberry Pi as part of their "common" baseline. The role’s default configuration will detect the absence of AppArmor on a Raspbian system and, if running on Raspberry Pi hardware, will automatically build and install a new kernel with AppArmor support enabled by default.
Enabling AppArmor at boot time on a Raspberry Pi¶
Assuming you have built a kernel with AppArmor support for a Raspberry Pi, you can enable AppArmor support by passing the
security=apparmor options via the kernel command line. This may be necessary if
aa-status reports output such as:
apparmor module is loaded. apparmor filesystem is not mounted.
The above indicates the kernel supports AppArmor (i.e., the “
apparmor module is loaded.”) but that it is currently not enabled (i.e., the “
apparmor filesystem is not mounted.”). In such a situation, you can also confirm that this is the case by invoking
aa-enabled, which should respond with
No - disabled at boot..
On physical RPi devices, the bootloader is in the firmware (there is no separate bootloader such as GRUB) itself. It’s designed to read its kernel command line arguments from a file located at
/boot/cmdline.txt. Simply append the AppArmor options to this file, and then reboot the Raspberry Pi. For example:
cat /boot/cmdline.txt <(echo " apparmor=1 security=apparmor") | tr -d "\n"
Installing AppArmor profiles¶
In order for AppArmor to constrain a given process, a profile must be loaded for that process. Few software packages ship with AppArmor profiles for the programs they deliver, however additional profiles may be available from your OS distribution’s default package repositories. On a Debian-based system, install them with:
sudo apt update && sudo apt install apparmor-profiles # Additional AppArmor profiles are available in the apparmor-profiles-extra package. sudo apt install apparmor-profiles-extra
AppArmor profiles are loaded from plain text files written in a DSL. See the
apparmor.d(8) manual page for details regarding the syntax of an AppArmor profile file. These files can then be parsed and subsquently loaded into the kernel using the
AppArmor profile directory structure¶
By convention, AppArmor profile files should be placed into the
/etc/apparmor.d directory. This directory is structured as follows:
/etc/apparmor.d/– Base directory containing AppArmor profile files.
bin.ping– Profile file for the
/bin/pingexecutable. Files are named with a dot-separated notation that matches their installed filesystem path. (This is just a convention, see the contents of the file for the process to which the profile will actually be applied. See, for example,
local/– Conventional directory for site-specific overrides or extensions to a vendor’s AppArmor profile.
disable/– Directory containing symbolic links to profile files that are to be disabled (not enforced).