Android System Securing, Hardening, & Privacy

Demystifying Android SELinux Policy Patches: A Custom ROM Backporting Tutorial

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction: The Crucial Role of SELinux in Android Security

Security-Enhanced Linux (SELinux) is a fundamental component of Android’s security architecture, enforcing mandatory access control (MAC) over all processes, files, and resources. It operates on the principle of least privilege, ensuring that even if a service or application is compromised, its ability to inflict damage is severely limited. For custom ROM developers and users, staying up-to-date with Android’s security patches, especially those pertaining to SELinux policy, is paramount. These patches often fix critical vulnerabilities, prevent new attack vectors, and enhance overall system integrity.

This tutorial will guide you through the process of analyzing Android SELinux policy patches from AOSP (Android Open Source Project) and backporting them to your custom ROM. This is an expert-level guide requiring familiarity with Android’s build system, basic Linux command-line operations, and version control (Git).

Understanding Android SELinux Policy Structure

Android’s SELinux policy is compiled from a set of source files, primarily located in system/sepolicy/ and device/<vendor>/sepolicy-legacy-x/ (for older devices or vendor-specific additions). Key file types include:

  • .te (Type Enforcement) files: Define types, attributes, and rules for how these types interact. This is where most access control rules are specified (e.g., allow domain type:class operation;).
  • .fc (File Context) files: Map paths in the filesystem to specific SELinux types. This determines the initial context of files and directories.
  • .rc (Init Runtime Configuration) files: Define services and their initial SELinux domains.
  • neverallow rules: Critical sanity checks that explicitly forbid certain access patterns, ensuring that no policy rule can grant access that is inherently insecure.

When an Android device boots, the compiled SELinux policy is loaded into the kernel, becoming the bedrock of its security posture.

Identifying Relevant SELinux Patches in AOSP

The first step in backporting is finding the patches. AOSP Gerrit is the primary source for all Android code changes. You can search for SELinux-related commits using keywords like “selinux policy”, “security”, “DAC/MAC”, “CVE” or specific component names like “audioserver” or “mediaserver” combined with “sepolicy”.

Let’s consider an example where a vulnerability might require a new SELinux type or a stricter access rule. You would typically look for commits affecting files in system/sepolicy/ or your device’s vendor sepolicy directory.

Example Gerrit Search:

project:platform/system/sepolicy branch:android-13 selinux policy OR security

This search would show all commits to the platform/system/sepolicy project on the android-13 branch that contain “selinux policy” or “security”. Look for commits marked as security fixes or related to specific CVEs.

Analyzing a SELinux Policy Patch

Once you’ve identified a potential patch, it’s crucial to understand what it does. Let’s assume we found a commit that adds a new permission check for a hypothetical service. The commit might look something like this:

commit <commit_hash>Author: AOSP Contributor <[email protected]>Date: Mon Jan 1 00:00:00 2023 +0000    Fix: CVE-2023-XXXX Prevent unauthorized access to new_device_service.    This patch restricts access to new_device_service to only trusted_app domains by introducing a new type and associated rules.diff --git a/system/sepolicy/public/attributes b/system/sepolicy/public/attributesindex <hash>..<hash> 100644--- a/system/sepolicy/public/attributes+++ b/system/sepolicy/public/attributes@@ -XX,XX +XX,XX @@attribute_set oem_exec_file;+attribute new_device_service_client;+type new_device_service_daemon, domain;+type new_device_service_socket, file_type;+...diff --git a/system/sepolicy/public/domain.te b/system/sepolicy/public/domain.teindex <hash>..<hash> 100644--- a/system/sepolicy/public/domain.te+++ b/system/sepolicy/public/domain.te@@ -YY,YY +YY,YY @@# Allow trusted apps to bind to new_device_service.+-allow trusted_app new_device_service_daemon:unix_stream_socket connectto;+allow trusted_app new_device_service_socket:unix_stream_socket connectto;...diff --git a/system/sepolicy/public/file.te b/system/sepolicy/public/file.teindex <hash>..<hash> 100644--- a/system/sepolicy/public/file.te+++ b/system/sepolicy/public/file.te@@ -ZZ,ZZ +ZZ,ZZ @@# New device service socket context.+type new_device_service_socket, file_type;...diff --git a/system/sepolicy/private/file_contexts b/system/sepolicy/private/file_contextsindex <hash>..<hash> 100644--- a/system/sepolicy/private/file_contexts+++ b/system/sepolicy/private/file_contexts@@ -AA,AA +AA,AA @@/dev/socket/new_device_service u:object_r:new_device_service_socket:s0

From this hypothetical diff, you can see new types (new_device_service_daemon, new_device_service_socket) are introduced, existing rules are modified or new ones added (e.g., specific allow rules for trusted_app), and file contexts are updated (/dev/socket/new_device_service). This patch prevents unauthorized domains from interacting with the new service.

Backporting the Patch to Your Custom ROM

Step 1: Locate Target Files in Your Custom ROM Source

Your custom ROM’s source tree will have similar SELinux policy files. Depending on your base Android version and device, these files might be in:

  • system/sepolicy/ (for generic policy)
  • device/<vendor>/<device>/sepolicy/ (device-specific policy)
  • vendor/qcom/sepolicy-legacy-x/ (for Qualcomm-based devices)
  • Or similar paths.

Identify the exact files mentioned in the AOSP patch within your custom ROM’s source. If your custom ROM is based on an older Android version, the structure might differ slightly, requiring careful adaptation.

Step 2: Apply Changes Manually or via git cherry-pick

Directly applying a patch using git cherry-pick <commit_hash> is ideal, but often leads to conflicts, especially if your custom ROM has diverged significantly or is based on an older AOSP branch. When conflicts arise:

  1. Attempt git cherry-pick -x <commit_hash>: This command attempts to apply the patch while retaining the original commit information.

  2. Resolve Conflicts: Git will mark conflicting files. Open them and manually merge the changes. Pay close attention to line numbers and context. SELinux policy files are highly sensitive; a single misplaced line can cause boot loops.

    <<<<<<< HEAD// Your current code=======// The incoming change>>>>>>> <commit_hash>

    Manually edit the file to incorporate both desired changes, then `git add <file>` and `git commit`.

  3. Manual Application (Recommended for complex or old patches): For older or highly conflicted patches, it’s often safer to manually open the original AOSP diff and re-implement the changes line by line in your source. This allows you to understand each change in context and adapt it to your ROM’s specific policy.

Step 3: Building and Testing

After applying the changes, a full clean build of your custom ROM is necessary.

  1. Clean Build:

    cd <your_rom_source>. build/envsetup.shlunch <your_device_name> -userdebugmake cleanmake -j$(nproc --all)

    Ensure the build completes without SELinux-related errors.

  2. Flash the ROM: Flash the newly built ROM to your device.

  3. Verify Policy Changes:

    • Check SELinux enforcing status:

      adb shell su -c "getenforce"

      It should return `Enforcing`.

    • Monitor kernel logs for AVC denials:

      adb shell dmesg | grep selinux

      Look for `avc: denied` messages, which indicate policy violations. If you see denials related to the service or feature you patched, your policy might still be incomplete or incorrect.

    • Use audit2allow: If you encounter AVC denials, audit2allow is an invaluable tool. Copy your device’s `dmesg` output (or `audit.log` from `/data/misc/audit/`) to your PC and run:

      audit2allow -i <dmesg_output.txt> -p <path_to_sepolicy_source_on_pc>

      This will suggest new SELinux rules that would allow the denied operations. Caution: Do not blindly apply `audit2allow` suggestions. Analyze them carefully to ensure they don’t open new security holes.

Common Pitfalls and Troubleshooting

  • Build Failures: Syntax errors in `.te` or `.fc` files will prevent the policy from compiling. The build system usually provides clear error messages.
  • Boot Loops/Device Instability: Severely incorrect or incomplete policies can cause critical system services to fail, leading to boot loops or device unresponsiveness. This often indicates a `neverallow` violation or a missing critical permission.
  • `neverallow` Violations: If your patch introduces an allowance that violates a `neverallow` rule, the policy will fail to build. You must reconcile the `neverallow` rule or justify why it should be modified (rarely recommended for security patches).
  • AVC Denials: As mentioned, use `dmesg` and `audit2allow` to diagnose. Always aim for a clean boot with no new `avc: denied` messages after applying a patch.

Conclusion

Backporting Android SELinux policy patches is a critical but often challenging task for custom ROM maintainers. It requires a deep understanding of SELinux, meticulous attention to detail, and thorough testing. By diligently applying these patches, you contribute significantly to the security and stability of your custom ROM, protecting users from known vulnerabilities and maintaining a robust security posture against evolving threats. Regularly checking AOSP for security updates and integrating them into your build process is the hallmark of a responsible custom ROM developer.

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 →
Google AdSense Inline Placement - Content Footer banner