AppArmor
AppArmor profile enforcement, complain mode, aa-genprof for profile generation, and profile management.
AppArmor Status
sudo aa-status
apparmor module is loaded. 54 profiles are loaded. 34 profiles are in enforce mode. 20 profiles are in complain mode. 3 processes have profiles defined. 3 processes are in enforce mode. 0 processes are in complain mode. 0 processes are unconfined but have a profile defined.
sudo aa-enabled
cat /sys/module/apparmor/parameters/enabled
Profile Modes
YAppArmor profiles have two modes:
-
Enforce — blocks violations and logs them
-
Complain — logs violations but doesn’t block (for testing)
sudo aa-enforce /etc/apparmor.d/usr.bin.firefox
sudo aa-complain /etc/apparmor.d/usr.bin.firefox
sudo aa-disable /etc/apparmor.d/usr.bin.firefox
sudo systemctl reload apparmor
Profile Locations
/etc/apparmor.d/ # Profile definitions /etc/apparmor.d/abstractions/ # Shared rule fragments (like partials!) /etc/apparmor.d/tunables/ # Variables (home dir, system paths) /etc/apparmor.d/local/ # Local overrides (survive package updates)
ls /etc/apparmor.d/
cat /etc/apparmor.d/usr.bin.firefox
Profile Syntax
AppArmor profiles are human-readable — one of its advantages over SELinux.
#include <tunables/global>
/usr/bin/myapp {
#include <abstractions/base> # Common system access
#include <abstractions/nameservice> # DNS, users, groups
# File access rules
/etc/myapp.conf r, # Read config
/var/log/myapp.log w, # Write log
/var/lib/myapp/** rw, # Read/write data directory
/tmp/myapp.* rw, # Temp files
# Network access
network inet stream, # TCP
network inet dgram, # UDP
# Capability
capability net_bind_service, # Bind to ports < 1024
# Deny explicitly
deny /etc/shadow r, # Never read shadow
deny /root/** rwx, # Never touch root's home
}
r — read w — write a — append x — execute m — memory map executable k — lock l — link
Creating a New Profile
sudo aa-genprof /usr/bin/myapp
This starts the app, watches what it accesses, and asks you to allow/deny each access. Creates the profile automatically.
# 1. Create a basic complain-mode profile
sudo aa-autodep /usr/bin/myapp
# 2. Run the application, exercise all features
# 3. Scan logs and update profile
sudo aa-logprof
# 4. Switch to enforce
sudo aa-enforce /etc/apparmor.d/usr.bin.myapp
Troubleshooting
sudo journalctl -k | grep apparmor | grep DENIED | tail -20
dmesg | grep apparmor | grep DENIED
apparmor="DENIED" operation="open" profile="/usr/bin/myapp" name="/etc/secret.conf" pid=12345 comm="myapp" requested_mask="r" denied_mask="r"
This tells you: myapp tried to read /etc/secret.conf and was denied. Add r permission for that path in the profile.
# The denial says: name="/etc/secret.conf" requested_mask="r"
# Add to profile: /etc/secret.conf r,
sudo aa-logprof
Arch Linux Specifics
sudo pacman -S apparmor
# Add to /boot/loader/entries/*.conf (systemd-boot) or GRUB:
apparmor=1 security=apparmor
sudo systemctl enable --now apparmor
# AUR: apparmor-profiles
yay -S apparmor-profiles
AppArmor vs SELinux
| Dimension | AppArmor | SELinux |
|---|---|---|
Default on |
Debian, Ubuntu, SUSE, Arch |
RHEL, CentOS, Fedora, Rocky |
Model |
Path-based (file paths) |
Label-based (file contexts) |
Profile format |
Human-readable text |
Complex policy modules (binary) |
Learning curve |
Lower — profiles are intuitive |
Higher — contexts, booleans, types |
Granularity |
Per-application |
System-wide (every file, process, port) |
Tools |
aa-status, aa-enforce, aa-genprof, aa-logprof |
getenforce, semanage, restorecon, audit2allow |
Troubleshooting |
|
|
RHCSA exam |
Not tested |
Required — contexts, booleans, ports |
Real-World: P16g AppArmor Deployment
From CR-2026-04-04:
# 1. Install
sudo pacman -S apparmor
# 2. Enable kernel parameter
# In /boot/loader/entries/arch.conf:
# options ... apparmor=1 security=apparmor
# 3. Enable service
sudo systemctl enable --now apparmor
# 4. Verify
sudo aa-status
/usr/bin/firefox — browser isolation /usr/lib/thunderbird — email isolation /usr/bin/evince — PDF reader isolation /snap/snapd/*/snapd — snap confinement
Quick Decision Tree
Q: Which MAC system am I using? ├── RHEL/CentOS/Rocky/Fedora → SELinux ├── Arch/Debian/Ubuntu/SUSE → AppArmor └── Both (like you) → Learn both. SELinux for RHCSA. AppArmor for daily driver. Q: Something was denied — how do I fix it? ├── SELinux: ausearch -m AVC → restorecon or setsebool or semanage fcontext └── AppArmor: journalctl -k | grep DENIED → edit profile or aa-logprof
See Also
-
SELinux — alternative MAC framework
-
Permissions — DAC layer that AppArmor supplements