SELinux策略配置在Android内核中的实战应用 - 第1节
1.1 什么是 SELinux
SELinux(Security-Enhanced Linux)是一个由美国国家安全局(NSA)开发的 Linux 内核安全模块,它通过强制访问控制(MAC)机制,为系统提供细粒度的权限管理。在 Android 系统中,SELinux 被集成到内核中,用于限制进程和用户对文件、设备、网络等资源的访问,即使进程以 root 权限运行,也无法绕过 SELinux 的策略约束。
核心思想:SELinux 遵循“默认拒绝”原则——任何未被明确允许的访问操作都会被阻止。这与传统 Linux 的“默认允许”权限模型形成鲜明对比。
SELinux 的工作模式
SELinux 支持三种工作模式,在 Android 中通常使用 Enforcing 模式以确保安全策略强制执行:
| 模式 | 行为 | Android 默认状态 |
|---|---|---|
| Enforcing | 强制执行策略,拒绝违规操作并记录日志 | Android 5.0+ 默认启用 |
| Permissive | 不阻止违规操作,仅记录警告日志 | 仅用于调试或开发阶段 |
| Disabled | 完全关闭 SELinux,不进行任何检查 | 不推荐,会降低系统安全性 |
实战提示:在开发自定义 SELinux 策略时,建议先在 Permissive 模式下收集审计日志(avc: denied),确认所有必要的访问权限都被正确允许后,再切换到 Enforcing 模式。
1.2 MAC 与 DAC 的区别
理解 SELinux 的关键在于区分自主访问控制(DAC)和强制访问控制(MAC)。传统 Linux 使用 DAC,而 SELinux 在 DAC 之上叠加了 MAC 层。
DAC(自主访问控制)
在 DAC 模型中,资源的拥有者可以自行决定谁可以访问该资源。例如,文件所有者可以通过 chmod 命令设置文件权限(rwx)。DAC 的局限性在于:
- 权限提升漏洞:一旦进程获得 root 权限,它可以访问系统上所有资源。
- 粗粒度:权限仅基于用户、组、其他三类,无法精确控制“某个特定进程”对“某个特定文件”的操作。
- 无类型强制:无法区分“系统服务”和“用户应用”的访问行为。
MAC(强制访问控制)
MAC 由系统管理员(或策略文件)统一制定规则,所有主体(进程)和客体(文件、端口等)都被赋予安全上下文(Security Context)。访问决策基于预定义的策略,而非资源拥有者的意愿。MAC 的优势:
- 最小权限原则:即使进程以 root 运行,也只能访问策略允许的资源。
- 细粒度控制:可以精确到“哪个进程”对“哪个文件”进行“哪种操作”(读、写、执行等)。
- 隔离性:不同安全域的应用和服务被严格隔离,防止横向移动攻击。
对比表格
| 特性 | DAC(传统 Linux) | MAC(SELinux) |
|---|---|---|
| 控制粒度 | 用户/组/其他(3 类) | 进程 × 文件 × 操作(任意组合) |
| 权限继承 | 子进程继承父进程权限 | 子进程拥有独立的安全上下文 |
| root 用户限制 | 无限制(root 可做任何事) | 受策略约束(root 也无法绕过) |
| 策略管理 | 由资源所有者管理 | 由系统策略文件统一管理 |
| 默认行为 | 允许(除非明确拒绝) | 拒绝(除非明确允许) |
常见误区:很多开发者认为“只要关闭 SELinux 或设为 Permissive 模式,应用就能正常工作”。实际上,这会导致系统安全防护降级,且无法通过 CTS(兼容性测试套件)认证。正确的做法是为应用编写合适的 SELinux 策略。
1.3 SELinux 在 Android 安全体系中的角色
Android 的安全体系是一个多层防御模型,SELinux 位于最底层的内核安全层,与其他安全机制协同工作:
SELinux 在 Android 中的关键作用
- 限制系统服务:即使系统服务(如
mediaserver、surfaceflinger)被攻破,SELinux 策略也能阻止其访问非授权的文件或设备。 - 隔离应用数据:不同应用之间的数据访问受到严格限制,即使它们拥有相同的 UID,SELinux 也能通过类型强制(Type Enforcement)进行二次隔离。
- 保护内核对象:控制对
/proc、/sys等敏感文件系统的访问,防止恶意进程篡改内核参数或获取系统信息。 - 支持多用户场景:在 Android 多用户或工作资料(Work Profile)模式下,SELinux 确保不同用户的数据完全隔离。
安全事件处理流程
当 SELinux 阻止一个访问请求时,会生成一条审计日志(通常包含 avc: denied 关键字)。开发者可以通过分析这些日志来调整策略:
# 查看 SELinux 审计日志(需要 root 权限)
adb shell dmesg | grep "avc: denied"
# 示例输出:
# type=1400 audit(123456.789:0): avc: denied { read } for pid=1234 comm="app_process" name="secret.txt" dev="mmcblk0" ino=5678 scontext=u:r:untrusted_app:s0 tcontext=u:object_r:app_data_file:s0 tclass=file permissive=0
实战技巧:在开发阶段,可以使用
adb shell setenforce 0 临时切换到 Permissive 模式,然后运行应用并收集所有 avc: denied 日志。将这些日志导入 audit2allow 工具,可以自动生成所需的 SELinux 策略规则。
SELinux 与 Android 安全机制的协同
| 安全机制 | 层级 | 与 SELinux 的关系 |
|---|---|---|
| 应用沙箱(UID/GID) | 应用层 | SELinux 在 DAC 之上提供第二层隔离,防止 UID 泄露后的越权访问 |
| Android 权限系统 | 框架层 | SELinux 控制底层资源访问,Android 权限控制高层 API 调用 |
| seccomp-bpf | 内核层 | seccomp 限制系统调用,SELinux 限制内核对象访问,两者互补 |
| Verified Boot | 硬件层 | 确保系统分区完整性,SELinux 策略文件在验证后加载 |
重要提醒:SELinux 不是万能的。它无法防御内核漏洞(如内核提权漏洞),也无法阻止应用层的逻辑攻击。SELinux 是纵深防御体系中的一环,必须与其他安全机制配合使用才能发挥最大效果。