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 四个文件的关系

讲到这里,你可能有点晕。这四个文件到底怎么配合工作的?我画个简单的流程:

  1. 系统启动时,init 进程读取 file_contexts,给所有文件打上标签
  2. 应用启动时,zygote 根据 seapp_contexts,决定进程的 domain
  3. 进程运行时,内核根据 te 文件里的 allow 规则,检查每次访问是否合法
  4. 读写系统属性时,内核根据 property_contexts 检查权限

你看,一环扣一环。任何一个文件配错了,都会导致权限问题。

文件 作用 常见问题
te 文件 定义类型和访问规则 漏写 allow 规则导致 avc denied
file_contexts 文件路径到安全上下文的映射 路径正则写错,文件标签不对
property_contexts 系统属性到安全上下文的映射 属性前缀匹配顺序错误
seapp_contexts 应用进程的安全上下文分配 匹配顺序不对,应用 domain 分配错误

总结一下:这四个文件是 SELinux 策略的四大支柱。te 文件定规则,file_contexts 和 property_contexts 定标签,seapp_contexts 定进程身份。搞懂了它们,你就掌握了 SELinux 策略移植的核心。

嗯,今天就先讲到这里。下一章我会带你实战——怎么在 AOSP 里添加一个新的系统服务,并给它配置完整的 SELinux 策略。到时候咱们再细聊。