Introduction: The Unyielding Guard of Android SELinux
Android’s security model relies heavily on SELinux (Security-Enhanced Linux), a mandatory access control (MAC) system that enforces granular permissions beyond traditional Linux discretionary access control (DAC). At its core, SELinux prevents processes from performing actions not explicitly permitted by the policy. Among the most stringent directives in SELinux policy are neverallow rules. These rules are compile-time assertions designed to guarantee that certain critical security invariants are maintained, acting as a safeguard against accidental policy relaxations or subtle logic errors that could lead to privilege escalation. For security researchers and penetration testers, understanding and potentially circumventing neverallow rules is crucial for discovering novel attack paths.
Understanding ‘neverallow’ Rules in SELinux
A neverallow rule is a powerful declarative statement within an SELinux policy that forbids a specific interaction between a source domain, a target type, and a set of permissions. Unlike regular allow rules, which grant permissions, neverallow rules explicitly deny them, and this denial is enforced during policy compilation. If any combination of allow rules in the policy would, even indirectly, grant a permission forbidden by a neverallow rule, the policy compilation will fail.
The primary purpose of neverallow rules is multifaceted:
- Preventing Policy Bugs: They act as a sanity check, catching errors where developers might inadvertently grant overly broad permissions.
- Enforcing Security Critical Invariants: For example, ensuring that untrusted applications can never directly access highly sensitive system resources or perform actions that would compromise the system’s integrity.
- Simplifying Policy Audits: By explicitly stating what *should never* happen, it makes policy review clearer and helps maintain a robust security posture over time, even as the policy evolves.
A typical neverallow rule might look like this:
neverallow untrusted_app { system_file_type } { read write execute };
This rule explicitly states that the untrusted_app domain can never have read, write, or execute permissions on any resource labeled with system_file_type. If an allow rule, or a chain of allow rules, were to implicitly grant such access, the policy compiler would flag it as an error and refuse to build the policy.
Identifying ‘neverallow’ Violations
During development, neverallow violations are often caught by tools like sepolicy-analyze or during the policy compilation process itself. When a violation occurs, the compilation typically fails with a detailed error message indicating the specific neverallow rule that was broken and the offending allow rule(s).
For example, using sepolicy-analyze with a compiled policy:
sepolicy-analyze -P /path/to/sepolicy neverallow
This command can help identify existing neverallow rules. To detect potential violations, developers usually rely on the build system’s integrated checks.
The Challenge and Art of Bypassing ‘neverallow’ Rules
Directly
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 →