3. SELinux策略文件结构:te文件、file_contexts、property_contexts、seapp_contexts解析
好,咱们直接进入正题。SELinux 策略文件,说白了就是一套规则说明书。系统里每个进程、每个文件该有什么权限,全写在这些文件里。我刚开始接触 AOSP 安全框架时,面对一堆 .te、.contexts 文件,说实话有点懵。但摸清楚套路后,你会发现——其实没那么复杂。
今天我就带你把这几个核心文件拆开揉碎,一个一个讲清楚。
3.1 te 文件——策略的核心
te 文件,全称 Type Enforcement 文件。它是 SELinux 策略的基石。你想想看,系统里跑着上百个进程,每个进程能访问哪些文件、能调用哪些系统调用,全靠 te 文件来定义。
一个典型的 te 文件长这样:
type system_app, domain;
type system_app_data_file, file_type, data_file_type;
allow system_app system_app_data_file:dir rw_dir_perms;
allow system_app system_app_data_file:file create_file_perms;
这里我解释一下:
- type 关键字用来声明一个类型。第一个参数是类型名,后面是属性。
- allow 规则定义了主体(source)对客体(target)的访问权限。
- 格式是:
allow 主体类型 客体类型:类别 权限集合;
我在项目中遇到过一个问题:某个第三方应用老是崩溃,log 里报 avc denied。查了半天,原来是 te 文件里少写了一条 allow 规则,应用没法访问自己的数据目录。嗯,这种坑踩过一次就记住了。
核心要点:te 文件里定义的每个 type,最终都会编译进 policy.binary。系统启动时,内核加载这个二进制文件,然后所有访问控制都按它来执行。
3.2 file_contexts——文件标签的说明书
光有 te 文件还不够。你想想,系统怎么知道 /data/data/com.example.app 这个目录该用哪个安全上下文?答案就在 file_contexts 里。
file_contexts 文件定义了文件路径与安全上下文的映射关系。它的格式很简单:
/system/bin/app_process u:object_r:zygote_exec:s0
/data/data/(.*) u:object_r:app_data_file:s0:c512,c768
/vendor(/.*)? u:object_r:vendor_file:s0
每一行包含两部分:
- 左边是文件路径的正则表达式
- 右边是对应的安全上下文
这里有个细节要注意:匹配顺序很重要。系统会从上到下逐行匹配,第一个匹配到的规则生效。所以更具体的路径要写在前面,通用的写在后面。
我的习惯:每次添加新的应用数据目录,我都会先在 file_contexts 里加一行。不然就算 te 文件写得再对,文件标签不对,照样访问不了。我曾经因为这个排查了整整一下午,后来学乖了。
3.3 property_contexts——系统属性的安全门
Android 里有很多系统属性,比如 ro.build.version.sdk、persist.sys.timezone 这些。谁可以读、谁可以写,不能乱来。property_contexts 就是管这个的。
它的格式和 file_contexts 类似:
ro. u:object_r:default_prop:s0
ro.build. u:object_r:build_prop:s0
persist. u:object_r:persist_prop:s0
ctl. u:object_r:ctl_prop:s0
你看,不同前缀的属性被分配了不同的安全上下文。比如 ro. 开头的属性是只读的,普通应用根本改不了。ctl. 开头的属性用来控制系统服务,权限要求更高。
为什么要这么设计?说白了,就是防止恶意应用乱改系统属性。比如把 ro.secure 改成 0,那不就出大事了?
避坑指南:我曾经在移植时犯过一个错——把 persist 属性的上下文配错了。结果系统重启后,WiFi 密码、蓝牙配对信息全丢了。因为 persist 属性是用来保存持久化数据的,上下文不对,系统就没法正确读写。从那以后,我对 property_contexts 的每一行都格外小心。
3.4 seapp_contexts——应用进程的身份证
这个文件比较特殊,它专门用来给 Android 应用进程分配安全上下文。你安装一个 App,系统会根据它的 userId、包名、是否是系统应用等信息,决定它跑在哪个 domain 里。
看个例子:
isSystemServer=true domain=system_server
user=system domain=system_app type=system_app_data_file
user=_app seinfo=platform domain=platform_app type=app_data_file
user=_app domain=untrusted_app type=app_data_file
这里的关键字段:
- user:指定 userId 范围,_app 表示普通应用
- seinfo:应用的签名信息,platform 表示平台签名
- domain:进程运行时的安全域
- type:应用数据文件的标签
匹配规则也是从上到下,第一个匹配的生效。所以 platform_app 要写在 untrusted_app 前面,不然所有应用都会被当成 untrusted_app。
3.5 四个文件的关系
讲到这里,你可能有点晕。这四个文件到底怎么配合工作的?我画个简单的流程:
- 系统启动时,init 进程读取 file_contexts,给所有文件打上标签
- 应用启动时,zygote 根据 seapp_contexts,决定进程的 domain
- 进程运行时,内核根据 te 文件里的 allow 规则,检查每次访问是否合法
- 读写系统属性时,内核根据 property_contexts 检查权限
你看,一环扣一环。任何一个文件配错了,都会导致权限问题。
| 文件 | 作用 | 常见问题 |
|---|---|---|
| te 文件 | 定义类型和访问规则 | 漏写 allow 规则导致 avc denied |
| file_contexts | 文件路径到安全上下文的映射 | 路径正则写错,文件标签不对 |
| property_contexts | 系统属性到安全上下文的映射 | 属性前缀匹配顺序错误 |
| seapp_contexts | 应用进程的安全上下文分配 | 匹配顺序不对,应用 domain 分配错误 |
总结一下:这四个文件是 SELinux 策略的四大支柱。te 文件定规则,file_contexts 和 property_contexts 定标签,seapp_contexts 定进程身份。搞懂了它们,你就掌握了 SELinux 策略移植的核心。
嗯,今天就先讲到这里。下一章我会带你实战——怎么在 AOSP 里添加一个新的系统服务,并给它配置完整的 SELinux 策略。到时候咱们再细聊。