SELinux on Android depends heavily on labels. File permissions still matter, but SELinux decisions often come down to whether files, processes, and filesystems carry the correct security context at the right time.
When developers first work with SELinux, it is easy to treat labeling as secondary configuration work. I used to think the same thing. The policies looked more important than the labels themselves.
In practice, labels are often the system’s real security map. A correct policy attached to the wrong context can behave like a broken policy entirely. Many Android SELinux problems that look like permission failures actually begin as labeling failures.
Takeaways
- SELinux labels identify how files, processes, and resources should be treated by policy.
- Android uses multiple labeling methods depending on filesystem behavior.
- Extended attributes store security contexts directly on many filesystems.
file_contextsrules help assign labels during filesystem initialization and relabeling.- Dynamic transitions control how processes and newly created files inherit security types.
SELinux labels are the foundation of Android policy decisions

SELinux policies depend on labels because the kernel evaluates interactions between labeled subjects and labeled objects.
A process is not simply “an app” or “a daemon” from SELinux’s perspective. It runs under a specific security context. Files, sockets, directories, and devices also carry contexts.
When one component interacts with another, SELinux evaluates the relationship between those labels before allowing access.
I think this is one of the most important mental shifts for people coming from traditional Linux permissions.
Classic UNIX permissions mostly ask:
Who owns this file and what permissions are set?
SELinux asks something more specific:
What type of object is this, what type of process is interacting with it, and does policy allow the interaction?
That distinction makes labeling infrastructure extremely important.
Android uses multiple labeling strategies because filesystems behave differently

One thing that surprised me when digging deeper into Android SELinux internals is how many different labeling mechanisms exist.
There is no single universal method because filesystems do not all support security metadata in the same way.
Some filesystems support storing SELinux labels directly through extended attributes. Others require alternative labeling mechanisms managed externally through policy rules.
This creates an important operational reality:
SELinux labeling is partly a filesystem problem, not just a policy problem.
If developers ignore filesystem behavior, they can accidentally create inconsistent labeling environments where policy behaves unpredictably across partitions or storage types.
Extended attributes store labels directly on supported filesystems

Many modern Linux filesystems support extended attributes, often called xattrs.
These attributes allow filesystems to store additional metadata beyond normal ownership and permission bits.
SELinux uses this mechanism to attach security contexts directly to files and directories.
This approach has a major advantage:
The label travels with the object itself.
If a properly labeled file remains on a filesystem supporting xattrs, SELinux can retrieve the stored context directly during access checks.
I think this makes SELinux behavior much easier to reason about operationally because the filesystem itself carries part of the security model.
But there is also a practical risk.
If files move between filesystems with different labeling capabilities, contexts may become inconsistent or disappear entirely.
A developer copying files during Android image preparation or vendor customization can accidentally create labeling drift without realizing it.
file_contexts rules help rebuild labeling consistency

Android also relies heavily on file_contexts configuration files.
These rules map filesystem paths to expected SELinux labels.
During boot, image creation, or relabeling operations, the system uses these mappings to determine which contexts files should receive.
A simplified example might conceptually resemble:
/system/bin/some_service u:object_r:system_file:s0
The important idea is not the syntax itself. The important idea is that Android maintains expected labeling patterns for large parts of the filesystem hierarchy.
I think this is where SELinux labeling becomes more operational than theoretical.
Developers are not only writing policy rules. They are maintaining alignment between:
- Filesystem paths
- Runtime object types
- Expected process domains
- Actual deployed labels
When those pieces drift apart, denials often appear even if the policy logic itself is technically correct.
fs_use and genfscon exist because not every filesystem stores labels normally

Some filesystems either do not support extended attributes or behave differently enough that Android needs alternative labeling methods.
This is where mechanisms like fs_use and genfscon become important.
These policy mechanisms allow SELinux to assign contexts based on filesystem types or filesystem paths even when labels are not stored directly as xattrs.
I think this part is easy to underestimate because developers often focus mainly on ordinary files under familiar partitions.
But Android systems interact with many special filesystem types:
- procfs
- sysfs
- tmpfs
- device filesystems
- pseudo-filesystems exposed by the kernel
Many of these resources still require security labeling even though they do not behave like ordinary disk-backed files.
Without mechanisms like genfscon, SELinux would struggle to apply consistent policy enforcement across these dynamic kernel-managed resources.
Dynamic transitions control how labels evolve during runtime

SELinux labeling is not static.
Android systems constantly create:
- New processes
- Temporary files
- Sockets
- IPC objects
- Runtime-generated resources
SELinux therefore depends heavily on type transitions.
Type transitions determine how newly created objects receive labels based on:
- The creating process
- The parent object
- The policy rules involved
This becomes very important operationally.
Imagine a service creating temporary files during startup. If the files inherit incorrect contexts, later access attempts may fail even though the service itself operates correctly.
I would treat type transitions as one of the most important hidden parts of SELinux behavior because many runtime failures originate from incorrectly inherited labels rather than explicit permission gaps.
Relabeling workflows are part of normal Android maintenance
One thing I did not appreciate initially is how much Android SELinux depends on relabeling workflows remaining reliable.
Labels are not guaranteed to stay correct forever.
Filesystem repairs, vendor modifications, OTA updates, image rebuilding, or manual file operations can all introduce incorrect contexts.
That is why Android systems often include relabeling logic during boot or deployment procedures.
The system may:
- Verify expected contexts
- Restore labels from policy mappings
- Correct mismatched filesystem objects
- Apply recursive relabeling to partitions
I think this operational layer matters just as much as the policy itself.
A carefully designed policy becomes unreliable quickly if the filesystem state drifts away from the labels the policy expects.
Most SELinux labeling problems are really consistency problems
What stands out to me after looking closely at Android labeling systems is that SELinux security depends heavily on consistency across multiple moving parts.
The policy must expect the correct labels.
The filesystems must preserve those labels correctly.
The runtime transitions must generate expected labels dynamically.
The relabeling workflows must repair drift safely over time.
If one layer becomes inconsistent, the rest of the security model starts behaving unpredictably.
That is why Android SELinux implementation work often feels less like writing static security rules and more like maintaining a living labeling ecosystem across the entire operating system.
- SELinux label: A security context attached to a file, process, or resource that SELinux uses during policy decisions.
- Security context: A structured SELinux identity containing information such as type and domain labels.
- Extended attribute (xattr): Extra filesystem metadata used to store SELinux labels directly on supported filesystems.
file_contexts: SELinux configuration rules that map filesystem paths to expected labels.fs_use: A SELinux mechanism for assigning contexts to entire filesystem types.genfscon: A SELinux policy mechanism used to assign labels to special or pseudo-filesystems.- Type transition: A SELinux rule controlling how newly created processes or files receive security labels.
- Relabeling: The process of restoring or correcting SELinux labels on filesystems.
- procfs/sysfs: Special Linux pseudo-filesystems exposing kernel and system runtime information.
- Domain: The SELinux security type associated with a running process.
References:
- https://medium.com/@mayankzenmbm/the-complete-guide-to-selinux-in-android-from-core-concepts-to-deployment-59a3689c943c
- https://8ksec.io/android-selinux-internals-part-ii/
- https://stackoverflow.com/questions/57067494/how-process-under-android-selinux-context-was-labeled
- https://stackoverflow.com/a/57072052
- https://stackoverflow.com/questions/55163930/label-files-on-rootfs-ramdisk-with-selinux-context
- https://stackoverflow.com/questions/42682348/changing-selinux-context-of-a-file-on-android-not-working-properly
- https://source.android.com/docs/security/features/selinux/implement
- https://www.hsc.com/resources/blog/seandroid-selinux-making-devices-more-secure-a-technology-primer/
- https://www.youtube.com/watch?v=za433lS2gd0
- https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-security-enhanced_linux-working_with_selinux-selinux_contexts_labeling_files
- https://emteria.com/blog/selinux-android
- https://lineageos.org/engineering/HowTo-SELinux/