Advanced OS Customizations & Bootloaders

Demystifying Android SELinux Contexts: A Comprehensive Guide to Labels and Domains

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to Android SELinux

Security-Enhanced Linux (SELinux) is a mandatory access control (MAC) system implemented in the Linux kernel. On Android, SELinux is critical for enforcing security policies, preventing privilege escalation, and containing compromised services. Unlike traditional discretionary access control (DAC) systems, where resource owners define access, SELinux policies are system-wide and centrally managed, ensuring that even root cannot bypass predefined security rules without policy modification.

Understanding SELinux contexts, labels, and domains is fundamental to debugging security issues, developing custom ROMs, or performing advanced system customizations. Without this knowledge, encountering an “avc: denied” message can feel like hitting a brick wall. This guide will demystify these core concepts and provide practical steps for policy writing and debugging.

Understanding SELinux Contexts: The Core of Policy Enforcement

At the heart of SELinux is the concept of a “security context” (often simply called a “context”). Every file, process, and system object on an Android device has an associated SELinux context. This context is a string that tells the SELinux policy engine how that object should be treated.

The Anatomy of a Context: u:r:t:s

An SELinux context typically consists of four components: user, role, type, and sensitivity. While all four are present, the type identifier (often referred to as a “label”) is by far the most significant in Android’s simplified SELinux model:

u:r:t:s
  • u (User): In Android, this is almost always u (unconfined_u).
  • r (Role): Typically object_r for files and r (system_r) for processes.
  • t (Type/Label): This is the crucial part. It defines the identity and attributes of a file or process, determining what it can or cannot access. Examples include system_file, init, app_data_file.
  • s (Sensitivity/Category): Almost always s0 in Android. Used for Multi-Level Security (MLS), which is not extensively used in typical Android deployments.

For most practical purposes on Android, you’ll be focusing on the ‘type’ component. For instance, a system executable might have the context u:object_r:system_file:s0, while a process running an Android application might have u:r:untrusted_app:s0.

Domains and Types

The term “domain” specifically refers to the SELinux type of a process. A process running in the init domain can only perform actions allowed for the init type. Similarly, a file with the system_file type can only be accessed by processes that have been granted permission to interact with system_file objects.

SELinux policy rules define the interactions between domains and types. For example, an allow rule specifies that a particular source domain (process type) is permitted to perform certain operations (read, write, execute) on a target type (file, socket, etc.) of a specific class.

Initializing Contexts: file_contexts and genfs_contexts

How do objects get their initial contexts? This is primarily handled during system boot and filesystem mounting.

Labeling Filesystems with file_contexts

The primary mechanism for assigning SELinux contexts to files and directories on persistent filesystems (like /system, /vendor, /data) is through the file_contexts policy file. This file contains a list of regular expressions and their corresponding SELinux contexts.

When a filesystem is mounted, or when files are created, the system consults file_contexts to determine their initial label. If a file’s path matches an entry, it gets the specified context. If no explicit match is found, it usually defaults to a generic context like default_android_file or rootfs, which is often too restrictive.

# Example entries from a typical Android file_contexts file:
/init u:object_r:init_exec:s0
/vendor/bin(/.*)? u:object_r:vendor_file:s0
/system/bin/sh u:object_r:shell_exec:s0
/data/(media|misc|user|user_de|vendor_de|vendor)(/.*)? u:object_r:app_data_file:s0

Each line defines a path or a regex, followed by its security context. Modifying or extending file_contexts is a common task when adding new executables or data directories to your system.

Generic Filesystem Contexts (`genfs_contexts`)

For virtual filesystems like /proc, /sys, cgroup, and debugfs, which are not backed by persistent storage and whose contents change dynamically, genfs_contexts is used. This file defines default contexts for files within these filesystems based on their type and path.

# Example entry for a virtual filesystem:
genfscon proc / u:object_r:proc:s0
genfscon sysfs / u:object_r:sysfs:s0

These rules ensure that even dynamically generated files and directories in these virtual filesystems receive appropriate security labels.

Writing SELinux Policy Rules

SELinux policy rules are defined in .te (type enforcement) files, typically located in the /sepolicy directory of your Android source tree. These files are compiled into a single binary policy file (sepolicy or vendor_sepolicy) that the kernel loads at boot.

Basic Rule Types: allow, dontaudit, neverallow

  • allow source_domain target_type : class { permissions };

    This is the most common rule. It grants a process (source_domain) permission to perform specific operations (permissions like read, write, execute, getattr, connect) on objects labeled with target_type, belonging to a specific object class (e.g., file, socket, dir).

    # Example: Allow the system server to read system properties
    allow system_server property_type : property_service { get };
  • dontaudit source_domain target_type : class { permissions };

    This rule suppresses AVC denials for specific operations without actually allowing them. It’s often used during development to reduce log spam from known, harmless denials, but should be used sparingly in production as it hides potential security issues.

  • neverallow source_domain target_type : class { permissions };

    This rule explicitly forbids certain operations, and if a policy attempts to `allow` them, the policy compilation will fail. This is crucial for enforcing strong security invariants (e.g., preventing any app from writing to `/dev/mem`).

type_transition: Dynamic Context Changes

type_transition rules are essential for defining how processes change their context when executing programs or creating new files. This is not about granting permissions, but about defining the new security context for a new object.

# Syntax:
type_transition source_domain target_type : class default_type;
  • source_domain: The domain of the process performing the action.
  • target_type: The type of the object being acted upon (e.g., the executable being run, or the directory where a file is created).
  • class: The object class (e.g., process for executing, file for creating).
  • default_type: The new type the object will acquire.

A common use case is for a process (foo_domain) to execute an executable (bar_exec) and transition into a new domain (bar_domain):

# When 'foo_domain' executes an executable labeled 'bar_exec',
# the new process will run in the 'bar_domain'.
type_transition foo_domain bar_exec : process bar_domain;

Another use is for a process to create files with a specific label in a directory:

# When 'foo_domain' creates a file in a directory labeled 'bar_data_file',
# the newly created file will be labeled 'bar_specific_file'.
type_transition foo_domain bar_data_file : file bar_specific_file;

Debugging SELinux Denials: A Step-by-Step Guide

The most common scenario for interacting with SELinux policy is debugging “Access Vector Cache” (AVC) denials. These messages indicate that a requested operation was blocked by the SELinux policy.

Identifying Denials

You can find AVC denials in the kernel message buffer (dmesg) or Android’s logcat:

$ adb shell su -c

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