3. SELinux 模式与策略:Enforcing、Permissive、Disabled 模式切换,策略文件结构概述
SELinux 在 Android 内核中的运行模式决定了安全策略的生效程度。理解三种模式的区别、切换方法以及策略文件的组织架构,是进行 SELinux 策略配置与调试的基础。本章将系统讲解模式切换的实战操作,并剖析策略文件的物理结构与逻辑层次。
3.1 SELinux 三种运行模式
SELinux 提供三种运行模式,分别对应不同的安全策略执行力度。在 Android 系统中,通常仅在调试或开发阶段使用非 Enforcing 模式。
| 模式 | 内核行为 | 日志记录 | 权限拒绝效果 | Android 生产环境 |
|---|---|---|---|---|
| Enforcing | 强制加载并执行策略 | 记录被拒绝的访问(AVC) | 直接拒绝,进程无法访问 | 必须使用 |
| Permissive | 加载策略但不执行 | 记录所有被拒绝的访问(AVC) | 仅记录,不拒绝,允许访问 | 禁止使用 |
| Disabled | 完全禁用 SELinux | 不记录任何 SELinux 日志 | 无任何 SELinux 限制 | 禁止使用 |
实战提示:在 Android 开发板上调试新策略时,建议先切换至 Permissive 模式收集完整的 AVC 拒绝日志,待策略完善后再切回 Enforcing 模式验证。切勿在用户设备上长期开启 Permissive 模式。
3.2 模式切换实战操作
模式切换分为运行时临时切换与启动时持久化配置两种方式。以下为具体操作命令与配置方法。
3.2.1 运行时临时切换(需 root 权限)
使用 setenforce 命令可以立即切换当前系统的 SELinux 模式,重启后失效。
# 查看当前模式
getenforce
# 切换为 Permissive 模式(用于调试)
adb shell su -c "setenforce 0"
# 切换为 Enforcing 模式(恢复强制)
adb shell su -c "setenforce 1"
# 查看详细状态
adb shell su -c "cat /sys/fs/selinux/enforce"
3.2.2 启动时持久化配置
通过修改内核启动参数或设备树(DT)中的 androidboot.selinux 属性,可以实现开机时自动设定模式。
| 配置位置 | 参数示例 | 说明 |
|---|---|---|
| BoardConfig.mk | BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive |
编译时写入内核 cmdline |
| 设备树(DTS) | bootargs = "androidboot.selinux=disabled"; |
在 DTS 中指定启动参数 |
| fastboot 临时覆盖 | fastboot oem selinux permissive |
部分设备支持,重启后失效 |
安全警告:切勿在生产固件中设置
androidboot.selinux=disabled 或 permissive。这将完全关闭 Android 的安全增强机制,使系统暴露在恶意攻击风险之下。
3.3 模式切换流程示意图
下图展示了从系统启动到运行时模式切换的完整流程,以及各阶段对应的配置点。
3.4 策略文件结构概述
SELinux 策略文件在 Android 源码中具有清晰的物理存储结构与逻辑编译层次。理解这些文件的作用是编写和修改策略的前提。
3.4.1 物理文件结构
Android 的 SELinux 策略文件主要位于 system/sepolicy 目录下,采用模块化组织方式。
system/sepolicy/
├── public/ # 公共策略,所有平台共享
│ ├── attributes # 属性定义
│ ├── types # 类型定义
│ ├── roles # 角色定义
│ ├── users # 用户定义
│ └── initial_sids # 初始安全标识符
├── vendor/ # 厂商定制策略
│ ├── file_contexts # 文件安全上下文
│ ├── genfs_contexts # 虚拟文件系统上下文
│ ├── property_contexts # 属性安全上下文
│ ├── service_contexts # 服务安全上下文
│ └── seapp_contexts # 应用进程安全上下文
├── plat_sepolicy.cil # 平台编译后的 CIL 策略
├── vendor_sepolicy.cil # 厂商编译后的 CIL 策略
├── mapping/ # 版本映射文件
└── prebuilts/ # 预编译策略文件
3.4.2 核心策略文件功能对照
| 文件名 | 功能描述 | 编译产物 |
|---|---|---|
types |
定义所有 SELinux 类型(Type) | 类型标识符 |
attributes |
定义类型属性,用于批量授权 | 属性集合 |
file_contexts |
为文件系统路径分配安全上下文 | 二进制上下文文件 |
property_contexts |
为系统属性分配安全上下文 | 二进制上下文文件 |
service_contexts |
为 Binder 服务分配安全上下文 | 二进制上下文文件 |
seapp_contexts |
为 Android 应用进程分配安全上下文 | 二进制上下文文件 |
te_macros |
定义常用的 TE 规则宏 | 宏展开 |
3.5 策略文件编译与加载流程
下图展示了从策略源文件到内核加载的完整编译与部署链路。
3.6 策略文件编写示例
以下是一个简单的 TE(Type Enforcement)规则文件示例,展示了类型声明、属性关联和访问向量规则的写法。
# 文件: system/sepolicy/public/my_daemon.te
# 声明类型
type my_daemon, domain;
type my_daemon_exec, exec_type, file_type;
# 声明属性
typeattribute my_daemon mlstrustedsubject;
# 初始化进程域转换
init_daemon_domain(my_daemon)
# 允许 my_daemon 读取系统日志
allow my_daemon logd:unix_dgram_socket sendto;
allow my_daemon logd:fd use;
# 允许 my_daemon 访问自己的数据目录
allow my_daemon my_daemon_data_file:dir create_dir_perms;
allow my_daemon my_daemon_data_file:file create_file_perms;
# 允许 my_daemon 与 netd 通信
allow my_daemon netd:unix_stream_socket connectto;
关键概念:
- Type(类型):SELinux 安全上下文的核心组成部分,用于标识主体(进程)和客体(文件、套接字等)。
- Domain(域):进程的类型称为域,是 TE 规则中主体的身份。
- Attribute(属性):类型的标签,用于批量授权,减少规则数量。
- Allow 规则:格式为
allow source_type target_type:class perm_set;,是策略配置的基本单元。
3.7 模式与策略的关联关系
理解模式与策略文件之间的依赖关系,有助于快速定位问题。
| 场景 | 模式 | 策略文件状态 | 系统行为 |
|---|---|---|---|
| 正常生产 | Enforcing | 完整加载 | 所有访问受策略约束 |
| 策略调试 | Permissive | 完整加载 | 记录拒绝但不拦截 |
| 策略开发初期 | Permissive | 部分加载 | 仅记录已加载策略的拒绝 |
| 内核调试 | Disabled | 不加载 | 无任何 SELinux 功能 |
常见误区:Permissive 模式下策略文件仍然被完整加载和解析,只是内核不执行权限检查。因此,Permissive 模式可以用于验证策略语法是否正确,以及收集完整的 AVC 拒绝日志。Disabled 模式则完全跳过策略加载,无法用于策略调试。