自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
供应商 init
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
init 进程具有几乎不受限制的权限,并可使用 system 分区和 vendor 分区中的输入脚本在启动过程中初始化系统。此访问权限会导致 Treble 系统/供应商拆分中出现巨大漏洞,因为供应商脚本可能会指示 init 访问不属于稳定系统-供应商 ABI(应用二进制接口)的文件、属性等。
供应商 init 已设计为使用单独的安全增强型 Linux (SELinux) 域 vendor_init
,以利用供应商专属权限来运行 /vendor
中的命令,从而填补此漏洞。
机制
供应商 init 会在启动过程的早期派生在 SELinux 环境 u:r:vendor_init:s0
中运行的 init 子进程。此 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
类型属性添加到设备专用 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)。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-03-26。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-03-26。"],[],[],null,["# Vendor init\n\nThe init process has nearly unrestricted permissions and uses input scripts from\nboth the system and vendor partitions to initialize the system during the boot\nprocess. This access causes a huge hole in the Treble system/vendor split, as\nvendor scripts may instruct init to access files, properties, etc. that don't\nform part of the stable system-vendor application binary interface (ABI).\n\n\n*Vendor init* is designed to close this hole by using a separate\nsecurity-enhanced Linux (SELinux) domain `vendor_init` to run\ncommands found in `/vendor` with vendor-specific permissions.\n\nMechanism\n---------\n\n\nVendor init forks a subprocess of init early in the boot process with the\nSELinux context `u:r:vendor_init:s0`. This SELinux context has\nconsiderably fewer permissions than the default init context and its access is\nconfined to files, properties, etc. that are either vendor-specific or part of\nthe stable system-vendor ABI.\n\n\nInit checks each script it loads to see if its path starts with\n`/vendor` and if so, tags it with an indication that its commands\nmust be run in the vendor init context. Each init builtin is annotated with a\nboolean that specifies whether or not the command must be run in the vendor init\nsubprocess:\n\n- Most commands that access the file system are annotated to run in the vendor init subprocess and are therefore subjected to the vendor init SEPolicy.\n- Most commands that impact internal init state (e.g., starting and stopping services) are run within the normal init process. These commands are made aware that a vendor script is calling them to do their own non-SELinux permissions handling.\n\n\nThe main processing loop of init contains a check that if a command is annotated\nto run in the vendor subprocess and originates from a vendor script, that\ncommand is sent through inter-process communication (IPC) to the vendor init\nsubprocess, which runs the command and sends the result back to init.\n\nUse vendor init\n---------------\n\n\nVendor init is enabled by default and its restrictions apply to all init scripts\npresent in the `/vendor` partition. Vendor init should be transparent\nto vendors whose scripts are already not accessing system only files,\nproperties, etc.\n\n\nHowever, if commands in a given vendor script violate the vendor init\nrestrictions, the commands fail. Failing commands have a line in the kernel\nlog (visible with dmesg) from init indicating failure. An SELinux audit\naccompanies any failing command that failed due to the SELinux policy. Example\nof a failure including an SELinux audit: \n\n```\ntype=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\ninit: 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\n```\n\n\nIf a command fails, there are two options:\n\n- If the command is failing due to an intended restriction (such as if the command is accessing a system file or property), the command must be re-implemented in a Treble-friendly way, going through only stable interfaces. Neverallow rules prevent adding permissions to access system files that aren't part of the stable system-vendor ABI.\n- If the SELinux label is new and isn't already granted permissions in the system `vendor_init.te` nor excluded permissions through the neverallow rules, the new label may be granted permissions in the device-specific `vendor_init.te`.\n\n\nFor devices launching before Android 9, the neverallows rules may be bypassed by\nadding the `data_between_core_and_vendor_violators` typeattribute to\nthe device-specific `vendor_init.te` file.\n\nCode locations\n--------------\n\n\nThe bulk of the logic for the vendor init IPC is in [system/core/init/subcontext.cpp](https://android.googlesource.com/platform/system/core/+/android16-release/init/subcontext.cpp).\n\n\nThe table of commands is in the `BuiltinFunctionMap` class in [system/core/init/builtins.cpp](https://android.googlesource.com/platform/system/core/+/android16-release/init/builtins.cpp)\nand includes annotations that indicate if the command must run in the vendor\ninit subprocess.\n\n\nThe SEPolicy for vendor init is split across the private ([system/sepolicy/private/vendor_init.te](https://android.googlesource.com/platform/system/sepolicy/+/android16-release/private/vendor_init.te))\nand public ([system/sepolicy/public/vendor_init.te](https://android.googlesource.com/platform/system/sepolicy/+/android16-release/public/vendor_init.te))\ndirectories in system/sepolicy."]]