供应商 init

init 进程具有几乎不受限制的权限,并使用来自系统分区和供应商分区的输入脚本在启动过程中初始化系统。这种访问会在 Treble 系统/供应商拆分中造成巨大的漏洞,因为供应商脚本可能会指示 init 访问不属于稳定的系统-供应商应用程序二进制接口 (ABI) 的文件、属性等。

供应商 init 旨在通过使用单独的增强安全性 Linux (SELinux) 域 vendor_init 运行在 /vendor 中找到的命令并使用供应商特定的权限来弥补此漏洞。

机制

供应商 init 在启动过程的早期分叉 init 的子进程,并使用 SELinux 上下文 u:r:vendor_init:s0。此 SELinux 上下文的权限比默认 init 上下文少得多,并且其访问权限仅限于供应商特定的文件、属性等,或者稳定的系统-供应商 ABI 的一部分。

Init 检查其加载的每个脚本,查看其路径是否以 /vendor 开头,如果是,则标记它,指示其命令必须在供应商 init 上下文中运行。每个 init 内置函数都使用一个布尔值进行注释,该布尔值指定命令是否必须在供应商 init 子进程中运行

  • 大多数访问文件系统的命令都注释为在供应商 init 子进程中运行,因此受制于供应商 init SEPolicy。
  • 大多数影响内部 init 状态(例如,启动和停止服务)的命令都在正常的 init 进程中运行。这些命令知道供应商脚本正在调用它们来执行自己的非 SELinux 权限处理。

init 的主处理循环包含一个检查,即如果命令被注释为在供应商子进程中运行并且源自供应商脚本,则该命令将通过进程间通信 (IPC) 发送到供应商 init 子进程,该子进程运行该命令并将结果发送回 init。

使用供应商 init

供应商 init 默认启用,其限制适用于 /vendor 分区中的所有 init 脚本。对于脚本已不访问仅限系统的文件、属性等的供应商,供应商 init 应该是透明的。

但是,如果给定供应商脚本中的命令违反了供应商 init 限制,则命令将失败。失败的命令在来自 init 的内核日志(使用 dmesg 可见)中有一行指示失败。SELinux 审核伴随任何由于 SELinux 策略而失败的命令。包含 SELinux 审核的失败示例

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

如果命令失败,则有两个选项

  • 如果命令由于预期限制而失败(例如,如果命令正在访问系统文件或属性),则必须以 Treble 友好的方式重新实施该命令,仅通过稳定的接口。Neverallow 规则阻止添加访问不属于稳定的系统-供应商 ABI 的系统文件的权限。
  • 如果 SELinux 标签是新的,并且尚未在系统 vendor_init.te 中授予权限,也没有通过 neverallow 规则排除权限,则可以在设备特定的 vendor_init.te 中授予新标签权限。

对于在 Android 9 之前发布的设备,可以通过将 data_between_core_and_vendor_violators typeattribute 添加到设备特定的 vendor_init.te 文件来绕过 neverallows 规则。

代码位置

供应商 init IPC 的大部分逻辑都在 system/core/init/subcontext.cpp 中。

命令表位于 system/core/init/builtins.cpp 中的 BuiltinFunctionMap 类中,并且包括指示命令是否必须在供应商 init 子进程中运行的注释。

供应商 init 的 SEPolicy 分布在 system/sepolicy 中的私有 (system/sepolicy/private/vendor_init.te) 和公共 (system/sepolicy/public/vendor_init.te) 目录中。