4. 安全上下文与文件标签
在 Android SELinux 中,策略规则本身并不直接绑定到某个具体文件或进程,而是绑定到安全上下文(Security Context)。系统在启动、创建文件、启动服务、设置属性时,会依据一系列标签文件为对象打上安全上下文,再由策略规则决定谁能访问谁。因此,理解安全上下文的格式以及 file_contexts、genfs_contexts、property_contexts、service_contexts 等标签文件的作用,是策略开发与调试的基础。
一、安全上下文的四元组格式
SELinux 安全上下文的标准格式为 user:role:type[:level],在 Android 中通常表现为三段或四段:
u:object_r:system_file:s0
u:r:init:s0
u:object_r:vendor_configs_file:s0
u:r:untrusted_app:s0:c512,c768
各字段含义如下:
- user:SELinux 用户,Android 中几乎恒为
u,不用于权限控制。 - role:角色,进程为
r,文件/属性等客体为object_r。 - type:类型,是 Android SELinux 真正起作用的核心字段,策略规则围绕 type 编写。
- level:MLS/MCS 敏感级别,如
s0;应用常带c512,c768这类类别,用于隔离不同应用。
u:object_r:foo:s0 与策略中定义的 foo 不一致,往往说明标签文件未生效或未重新编译加载。二、标签文件的作用与加载流程
标签文件是“路径/名称 → 安全上下文”的映射表。系统在编译时由 checkpolicy、sefcontext_compile 等工具将文本标签文件编译为二进制文件,运行时由 init、file_contexts 匹配逻辑、property_service、servicemanager 等组件读取并应用。
下图展示了从标签文件到对象打标签的整体数据流:
三、各类标签文件详解
Android 源码中,标签文件通常位于 system/sepolicy/ 及其子目录(如 private/、vendor/、public/)。不同标签文件对应不同对象类型,语法也略有差异。
| 标签文件 | 作用对象 | 典型语法 | 生效时机 |
|---|---|---|---|
| file_contexts | 普通文件、目录、符号链接 | /system/bin/init u:object_r:init_exec:s0 |
文件创建/访问时由内核匹配 |
| genfs_contexts | proc、sysfs、tmpfs 等伪文件系统 | genfscon proc / u:object_r:proc:s0 |
文件系统挂载时 |
| property_contexts | Android 系统属性 | ro.build.fingerprint u:object_r:build_prop:s0 |
属性设置/读取时 |
| service_contexts | Binder 服务名 | activity u:object_r:activity_service:s0 |
服务注册/查找时 |
| seapp_contexts | 应用进程 | user=system domain=system_app type=system_app_data_file |
zygote 孵化进程时 |
四、案例:为自定义可执行文件打标签
假设新增一个可执行文件 /system/bin/mydaemon,需要让它以 mydaemon 域运行。首先在 file_contexts 中声明其可执行标签:
# system/sepolicy/private/file_contexts
/system/bin/mydaemon u:object_r:mydaemon_exec:s0
然后在 mydaemon.te 中定义域与类型转换:
type mydaemon, domain;
type mydaemon_exec, exec_type, file_type, system_file_type;
init_daemon_domain(mydaemon, mydaemon_exec)
若该守护进程还需要访问某个属性,则在 property_contexts 中为其属性打标签:
# property_contexts
persist.mydaemon.enable u:object_r:mydaemon_prop:s0
编译后可通过以下命令验证标签是否生效:
adb shell ls -Z /system/bin/mydaemon
adb shell getprop -Z persist.mydaemon.enable
adb shell dumpsys activity service mydaemon | head
avc: denied 中出现的 type 与预期不符,或对象仍为 default_file_type、default_prop。五、常见误区与复盘
- 只改 .te 不改标签文件:策略中定义了新 type,但对象没有被打上该 type,规则永远不会命中。
- file_contexts 路径使用通配符过度:如
/data/.*会覆盖过多对象,导致应用数据目录标签混乱。 - genfs_contexts 与 file_contexts 混用:proc、sysfs 等伪文件系统必须用 genfscon,不能靠 file_contexts 匹配。
- property_contexts 前缀匹配顺序:属性标签按最长前缀匹配,短前缀可能被更长规则覆盖,需注意优先级。
- service_contexts 与 service.te 不一致:服务名标签与策略中
allow的 type 必须一致,否则 Binder 调用被拒。
vendor_boot 或 system 分区,仅 adb push 单个文件通常不会触发重新加载,调试时建议使用 adb shell dmesg | grep avc 确认实际生效的上下文。掌握安全上下文格式与各类标签文件的对应关系后,就能在遇到 avc denied 时快速判断:是策略规则缺失,还是对象根本没有被正确打标签。下一阶段将进入具体策略规则的编写与调试方法。