In the landscape of Linux security, Mandatory Access Control (MAC) systems play a critical role in enforcing granular access policies beyond the default Discretionary Access Control (DAC) model. Two of the most widely adopted MAC frameworks are SELinux (Security-Enhanced Linux) and AppArmor (Application Armor). Both aim to restrict process capabilities and mitigate vulnerabilities, but they differ significantly in design, complexity, and use cases. This blog provides a deep dive into SELinux and AppArmor, covering their fundamental concepts, usage methods, common practices, and best practices. By the end, you’ll understand their strengths, weaknesses, and which is better suited for your environment.
Table of Contents
- Introduction
- Fundamental Concepts
- Key Differences: SELinux vs. AppArmor
- Usage Methods
- Common Practices
- Best Practices
- Conclusion
- References
Fundamental Concepts
What Are Linux Security Modules (LSMs)?
Linux Security Modules (LSMs) are a kernel-level framework that enables the implementation of MAC systems. Unlike DAC, which relies on user/group permissions (e.g., chmod), MAC enforces policies based on system-wide rules, restricting even privileged users (e.g., root) from unauthorized actions. SELinux and AppArmor are the most popular LSM implementations.
SELinux Basics
Developed by the NSA in the late 1990s, SELinux is a robust MAC framework integrated into the Linux kernel. It enforces policies based on type enforcement (TE), role-based access control (RBAC), and multi-level security (MLS).
- Type Enforcement (TE): The core of SELinux. Every process and file is assigned a “security context” (e.g.,
httpd_tfor Apache processes,httpd_sys_content_tfor web files). Rules define which types can access others (e.g., “httpd_tcan readhttpd_sys_content_tfiles”). - Policy Types: SELinux uses prebuilt policies like
targeted(default on most systems, restricts only critical services) orstrict(restricts all processes). - Complexity: Policies are written in a low-level language (XML/TE rules), making them powerful but difficult to author from scratch.
AppArmor Basics
AppArmor, initially developed by Immunix and later maintained by Novell/Canonical, is a lighter MAC framework focused on path-based access control. It restricts processes to predefined paths and actions (e.g., “Nginx can only read /var/www/html/* and listen on port 80”).
- Profiles: AppArmor enforces policies via “profiles”—human-readable text files that specify allowed paths, network access, and capabilities for a process (e.g.,
/etc/apparmor.d/usr.sbin.nginxfor Nginx). - Simplicity: Profiles use intuitive syntax (e.g.,
allow /var/www/html/** r;to allow read access to web files), making them easier to write and modify. - Learning Mode: AppArmor supports “complain mode,” where it logs violations without blocking them, helping build profiles incrementally.
Key Differences: SELinux vs. AppArmor
To choose between SELinux and AppArmor, it’s critical to understand their architectural and practical differences. The table below summarizes key distinctions:
| Feature | SELinux | AppArmor |
|---|---|---|
| Access Control Model | Type/role-based (abstract labels) | Path-based (concrete file paths) |
| Policy Language | Complex XML/TE rules (e.g., allow httpd_t httpd_sys_content_t:file read;) | Simple, human-readable profiles (e.g., allow /var/www/html/** r;) |
| Default Platforms | RHEL, CentOS, Fedora, Rocky Linux | Ubuntu, Debian, SUSE, openSUSE |
| Learning Curve | Steeper (requires understanding contexts) | Gentler (familiar file paths) |
| Granularity | High (enforces on users, roles, types) | Moderate (focused on processes/paths) |
| Profile Generation | Manual (via audit2allow) or prebuilt | Automated (via aa-genprof in complain mode) |
Usage Methods
Installation & Status Checks
Both SELinux and AppArmor are preinstalled on their respective default distributions. Use these commands to verify status:
SELinux
# Check SELinux status (enabled/disabled, enforcing/permissive)
sestatus
# Sample output:
# SELinux status: enabled
# SELinuxfs mount: /sys/fs/selinux
# SELinux root directory: /etc/selinux
# Loaded policy name: targeted
# Current mode: enforcing
# Mode from config file: enforcing
# Policy MLS status: enabled
# Policy deny_unknown status: allowed
# Memory protection checking: actual (secure)
# Max kernel policy version: 33
AppArmor
# Check AppArmor status (loaded profiles, modes)
aa-status
# Sample output:
# apparmor module is loaded.
# 14 profiles are loaded.
# 12 profiles are in enforce mode.
# /sbin/dhclient
# /usr/bin/evince
# /usr/bin/evince-previewer
# /usr/sbin/nginx
# ...
# 2 profiles are in complain mode.
# /usr/bin/firefox
# ...
Managing Policies
SELinux Policy Management
SELinux policies are managed with tools like semanage, setsebool, and restorecon:
-
Relabel Files: If a file’s context is incorrect (e.g., after moving files), restore it:
# Relabel a single file restorecon -v /var/www/html/index.html # Relabel an entire directory restorecon -Rv /var/www/html/ -
Modify Booleans: SELinux “booleans” toggle predefined rules (e.g., allowing Apache to serve HTTP over HTTPS):
# List all booleans getsebool -a | grep httpd # Allow Apache to connect to the network setsebool -P httpd_can_network_connect on -
Add Contexts: Define custom file contexts (e.g., for a new web directory):
# Add a context for /srv/web (persistent across reboots) semanage fcontext -a -t httpd_sys_content_t "/srv/web(/.*)?" # Apply the new context restorecon -Rv /srv/web/
AppArmor Profile Management
AppArmor profiles are stored in /etc/apparmor.d/ and managed with aa-genprof, aa-enforce, and aa-complain:
-
Generate a Profile: Use
aa-genprofto create a profile for a process (e.g., Nginx) by monitoring its activity:# Generate a profile for Nginx (starts in complain mode) aa-genprof nginx # Follow prompts to allow/deny logged accesses -
Edit a Profile: Manually refine profiles (e.g., restrict Nginx to port 80 only):
# Edit Nginx profile nano /etc/apparmor.d/usr.sbin.nginx # Add rule to allow port 80 (TCP) network inet tcp port 80, -
Switch Modes: Toggle between
enforce(block violations) andcomplain(log only):# Put Nginx in enforce mode aa-enforce /usr.sbin.nginx # Put Nginx in complain mode (for testing) aa-complain /usr.sbin.nginx
Troubleshooting
SELinux Troubleshooting
SELinux denials are logged to /var/log/audit/audit.log. Use audit2allow to analyze them:
# Find recent SELinux denials
grep "AVC" /var/log/audit/audit.log | tail -5
# Generate a policy module to allow denied actions (use cautiously!)
audit2allow -a -M mymodule
semodule -i mymodule.pp # Load the module
AppArmor Troubleshooting
AppArmor logs to /var/log/syslog or /var/log/audit/audit.log. Use aa-logprof to refine profiles based on logs:
# Analyze logs and update profiles interactively
aa-logprof
Common Practices
SELinux Common Practices
- Use Targeted Policy: The
targetedpolicy (default) balances security and usability by restricting only critical services (e.g., Apache, SSH). Avoidstrictunless you need it. - Avoid Permissive Mode: Permissive mode logs violations but doesn’t block them—use it only for debugging, not production.
- Leverage Prebuilt Policies: Most applications (e.g., Nginx, MySQL) have prebuilt SELinux policies. Avoid writing custom policies unless necessary.
AppArmor Common Practices
- Start with Complain Mode: Build profiles in
complainmode to log violations without blocking processes, then refine rules withaa-logprof. - Restrict Network Access: Explicitly define allowed ports in profiles (e.g.,
network inet tcp port 443for HTTPS) to limit attack surface. - Keep Profiles Minimal: Avoid overly broad rules (e.g.,
allow /** r;). Restrict paths to only what the process needs.
Best Practices
General Best Practices
- Least Privilege: Both frameworks enforce “least privilege”—restrict processes to only the resources they need.
- Test Policies: Always test policy changes in a staging environment before deploying to production.
- Monitor Logs: Regularly check SELinux/AppArmor logs for violations to identify misconfigurations or attacks.
SELinux-Specific Best Practices
- Understand Contexts: Use
ls -Z(files) andps -Z(processes) to inspect security contexts. For example:ls -Z /var/www/html/ # Show file contexts ps -Z | grep nginx # Show Nginx process context - Use
semanagefor Persistence: Tools likesemanageensure changes survive reboots (unlikechcon, which is temporary).
AppArmor-Specific Best Practices
- Avoid Wildcards: Overly broad wildcards (e.g.,
allow /var/** r;) weaken security. Use specific paths (e.g.,allow /var/www/html/* r;). - Sign Profiles: Sign profiles with
apparmor_parser -sto prevent tampering (requiresapparmor-utils).
Conclusion
SELinux and AppArmor are both powerful MAC frameworks, but they cater to different needs:
-
Choose SELinux if: You need granular, type-based control (e.g., government, finance, or high-security environments). It excels at enforcing complex rules across users, roles, and resources but requires steeper learning.
-
Choose AppArmor if: You prioritize simplicity and path-based control (e.g., desktop systems, small businesses, or developers). Its human-readable profiles and lower learning curve make it ideal for rapid deployment.
Ultimately, the “better” choice depends on your environment, expertise, and security requirements. Both can significantly harden a Linux system—what matters most is consistent policy management and monitoring.