Introduction to AppArmor and Android Security
AppArmor, a Linux Security Module (LSM), offers mandatory access control (MAC) by confining programs to a limited set of resources. While SELinux is the dominant MAC system in Android, integrating AppArmor provides an additional, fine-grained layer of security, especially for specific services or custom applications within a modified Android Open Source Project (AOSP) or custom ROM build. This deep dive will guide you through the process of baking custom AppArmor profiles directly into your Android build, enhancing the security posture of your custom OS.
Prerequisites and Understanding AppArmor in AOSP
Before diving into profile creation, it’s crucial to ensure your kernel supports AppArmor and to understand its place within the Android security ecosystem.
Kernel Configuration
Your kernel must be compiled with AppArmor support. Verify or enable the following options in your kernel’s .config file:
CONFIG_SECURITY_APPARMOR=y
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
CONFIG_SECURITY_APPARMOR_DEFAULT_UNCONFINED=y
CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 ensures AppArmor starts in enforcing mode by default, and CONFIG_AUDIT is essential for logging policy violations. Rebuild your kernel if these options are not enabled.
Existing Android Security Mechanisms
Android primarily uses SELinux, which operates at a different abstraction layer than AppArmor. AppArmor focuses on path-based access control, making it simpler to define policies for specific applications or services without extensive relabeling. The goal isn’t to replace SELinux but to augment it, offering defense-in-depth for critical components or new services introduced in your custom ROM.
Crafting Your Custom AppArmor Profiles
AppArmor profiles define what a program is allowed to do. They are typically stored in /etc/apparmor.d/ on a standard Linux system. For Android, we’ll integrate them into the root filesystem or /system/etc/apparmor.d.
AppArmor Profile Syntax Fundamentals
A basic profile specifies the executable path and then lists allowed actions. Here’s a simplified example for a hypothetical custom service called my_secure_service:
#include <abstractions/base>
profile my_secure_service /system/bin/my_secure_service {
# Capabilities
capability sys_chroot,
capability dac_override,
# Network access
network tcp,
network udp,
# File access rules
/system/bin/my_secure_service mr,
/data/my_service/ rw,
/data/my_service/** rwk,
/dev/urandom r,
# Process rules
# Allow exec, fork, change root
exec /system/bin/another_helper_binary mr,
chroot /data/my_service/chroot_env/,
# Deny all other access by default (implicit)
}
#include <abstractions/base>: Includes common rules for basic system operations.profile my_secure_service /system/bin/my_secure_service { ... }: Defines a profile for the executable at/system/bin/my_secure_service.capability sys_chroot, capability dac_override,: Grants specific kernel capabilities.network tcp, network udp,: Permits TCP and UDP network access./data/my_service/ rw, /data/my_service/** rwk,: Grants read/write access to the directory/data/my_service/and read/write/delete access to its contents recursively./dev/urandom r,: Allows read access to/dev/urandom.exec /system/bin/another_helper_binary mr,: Permits executing another binary,m(memory map) andr(read) permissions.
Profile Design Best Practices
- Least Privilege: Only grant the absolute minimum permissions required for the service to function.
- Audit Mode First: Develop and test profiles in complain mode (
aa-complain /path/to/profileorflags=(complain)in the profile itself) to identify denials without blocking execution. - Granularity: Create specific profiles for each distinct service or application rather than broad, encompassing policies.
- Auditing: Always monitor your system logs for AppArmor denials, especially after deploying new profiles.
Integrating Profiles into the AOSP Build System
This is where the magic happens – embedding your custom profiles directly into your Android build.
Placing Profile Files
Create a dedicated directory for your profiles within your device tree. For example:
device/<vendor>/<device-name>/apparmor/
├── my_secure_service
└── another_profile
Modifying Android.bp or Android.mk
You need to instruct the build system to copy these profiles to the target device. Using Android.bp (Soong build system) is the modern approach:
Create an Android.bp file in your device/<vendor>/<device-name>/apparmor/ directory:
// device/<vendor>/<device-name>/apparmor/Android.bp
fs_config {
name: "apparmor_profiles_fs_config",
src: [
"my_secure_service",
"another_profile",
],
path: "/system/etc/apparmor.d",
mode: "0644",
owner: "root",
group: "root",
}
// Add this to your device's main Android.bp or BoardConfig.mk for inclusion
// In device/<vendor>/<device-name>/<device-name>.mk or similar:
// PRODUCT_PACKAGES += apparmor_profiles_fs_config
Alternatively, with Android.mk (deprecated for newer AOSP versions):
# device/<vendor>/<device-name>/apparmor/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := apparmor.d-profiles
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/apparmor.d
LOCAL_SRC_FILES :=
my_secure_service
another_profile
include $(BUILD_PREBUILT)
Then, ensure this module is included in your device’s BoardConfig.mk or <device-name>.mk:
PRODUCT_PACKAGES += apparmor.d-profiles
Kernel Command Line Integration
To enable AppArmor at boot, modify your device’s BoardConfig.mk to add parameters to the kernel command line:
# BoardConfig.mk
BOARD_KERNEL_CMDLINE += apparmor=1 security=apparmor
This tells the kernel to enable AppArmor and use it as the primary security module. If SELinux is also present, they will often run concurrently, with AppArmor providing additional confinement. Ensure you rebuild your boot image (e.g., make bootimage or full AOSP build) after this change.
init.rc Modifications for Profile Loading
Once the profiles are on the device, they need to be loaded into the kernel. Android’s init system is the ideal place for this. AppArmor uses the apparmor_parser utility.
You’ll need to build apparmor_parser as part of your AOSP build. First, ensure the AppArmor user-space tools are available in your AOSP source (often under external/apparmor/ or similar). Then, add it to your PRODUCT_PACKAGES:
PRODUCT_PACKAGES += apparmor_parser
Then, modify your device’s init.rc (e.g., device/<vendor>/<device-name>/init.rc or a custom .rc file included by it) to load the profiles. A custom service might look like this:
service apparmor_loader /system/bin/apparmor_parser -r /system/etc/apparmor.d/*
class main
user root
group root system
oneshot
disabled
on property:sys.boot_completed=1
start apparmor_loader
on property:ro.boot.apparmor_mode=enforcing
start apparmor_loader
This service runs apparmor_parser with the -r flag (replace/reload) for all profiles in /system/etc/apparmor.d/. It’s set to run once the system has booted. You can also trigger it based on a custom boot property.
Enforcing and Testing Your Profiles
After a full AOSP build and flashing your device, it’s time to verify your AppArmor integration.
Booting and Verification
Upon booting, connect via adb shell and check the kernel logs:
adb shell dmesg | grep apparmor
adb shell dmesg | grep "AppArmor: AppArmor initialized"
You should see messages indicating AppArmor has initialized and loaded your profiles. Look for messages like "AppArmor: AppArmor initialized" and "AppArmor: <profile_name> (enforce) profile loaded".
Runtime Profile Status
You can inspect the loaded profiles directly from the kernel filesystem:
adb shell cat /sys/kernel/security/apparmor/profiles
This command lists all currently loaded AppArmor profiles and their enforcement status (enforce/complain).
Auditing and Debugging
If your service behaves unexpectedly, check the audit logs for denials. AppArmor violations are logged to the kernel ring buffer, accessible via dmesg and logcat:
adb shell dmesg | grep "apparmor="
adb shell logcat | grep "audit"
Look for lines indicating
Android Mobile Specs & Compare Directory
Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!
Compare Devices Specs →