The Danger of Implicit Trust
Standard Linux permissions leave a dangerous gap in a secure operating system. Files normally inherit permissions from the user who created them. If a compromised service creates a file in a shared directory, sensitive data might remain accessible to other malicious actors. The kernel needs a strict way to determine exactly which security label every file receives, regardless of who created it.
Android solves this problem by using a canonical mapping of file paths to security contexts. This mechanism ignores the identity of the file creator entirely. A system process and a compromised app writing to the same location will trigger the same labeling rules. The system relies on these absolute labels to enforce mandatory access control across the entire filesystem.
This absolute mapping ensures predictability. You never have to guess what security context a file will receive. The platform relies on a single source of truth to manage this mapping.
Mapping Paths with file_contexts
Hardcoding a list of security labels into every system service would be impossible to maintain. Services change, paths move, and policies update over time. The platform uses a file called file_contexts to act as the master dictionary for file labeling. This file maps regular expressions representing file paths directly to their required SELinux contexts.
The syntax pairs a regular expression with a target security context. This design allows you to label a specific binary or recursively label an entire directory tree with one rule.
# Exact path match
/system/bin/surfaceflinger u:object_r:surfaceflinger_exec:s0
# Recursive directory match
/data/vendor/wifi(/.*)? u:object_r:wifi_vendor_data_file:s0
By defining these rules globally, the system removes ambiguity during image creation or permission repair. Every component queries this exact same dictionary when trying to understand filesystem security.
How Labels Get Applied
A file receives its label in different ways depending on when it comes into existence. Build-time assignment works entirely differently than runtime assignment. Understanding this distinction prevents serious confusion when you debug unexpected permission denials.
The Android build system generates partition images on a host machine long before a device boots. A utility called setfiles reads the file_contexts definitions during this build phase. It stamps the correct SELinux labels directly onto the filesystem blocks before the image is even flashed.
Runtime creation forces the kernel to handle the assignment dynamically. The process creating the file and the security label of the parent directory both influence the final outcome. The kernel evaluates explicit rules in the SELinux policy to decide which label to apply.
The flowchart below shows how the kernel decides which label to apply to a newly created file at runtime. This visualization clarifies the priority order between explicit policy overrides and default inheritance. Look at how a filetrans rule intercepts the process and overrides the parent directory label.
The kernel first checks for a specific filetrans rule governing that location. If one exists, it applies the explicit label defined in the policy. If no rule exists, the file falls back to inheriting the label of its parent directory.
For example, if the init process creates a new socket file in /dev, the generic parent directory label would be too broad. An explicit filetrans rule dictates the exact, restricted label the new socket must receive.
Fixing Corrupted Labels
Pushing files manually to a device via the shell often applies the label of the shell process to the new file. This mismatch immediately causes permission denials when system services attempt to read the file you just pushed. You need a way to force the filesystem back into compliance with the official policy.
The restorecon utility exists to fix these exact mismatches. It reads the canonical file_contexts definitions and reapplies the correct labels to the specified paths. This operation provides the safest and most permanent way to fix label corruption during development.
# Restore a single file
adb shell restorecon /data/vendor/wifi/wpa_supplicant.conf
# Restore a directory recursively
adb shell restorecon -R /data/vendor/wifi/
Common Mistake: Running a directory sync command often leaves newly transferred files with incorrect shell labels. Always run
restorecon -Ron modified directories after syncing vendor or system files.
Testing a permission rule without modifying the central policy requires a manual override. The chcon tool lets you manually change a file context to any arbitrary value. This tool bypasses the file_contexts dictionary completely.
adb shell chcon u:object_r:audio_data_file:s0 /data/local/tmp/test.wav
Context overrides applied with chcon remain completely temporary. They will disappear the next time the system runs restorecon on that path.
Managing Dynamic Userdata
Files on the userdata partition are created dynamically and persist across device reboots. If an OTA update changes policy requirements, the existing userdata files might possess outdated security labels. The system must coordinate runtime creation permissions with the persistent labeling rules.
Developers must define the target path in file_contexts to ensure the label survives any future manual restore operation. The creating service also needs a filetrans rule in its SELinux policy. Without both pieces, the file might get created correctly but lose its label during an unexpected recovery.
When an OTA update adds new paths to file_contexts for the userdata partition, the system handles the transition automatically. It runs a restorecon pass over those specific directories during the very next boot. This synchronization ensures that legacy files receive the updated security labels required by the new policy.
These tools and rules guarantee that every file maintains a predictable security context. But defining file contexts is only half the battle. Next, we explore how processes interact with these labeled files using SELinux domains.