<devsite-heading text="供應(yīng)商 init" for="%E4%BE%9B%E5%BA%94%E5%95%86-init" level="h1" class="devsite-page-title"># 供應(yīng)商 init</devsite-heading>
init 進(jìn)程具有幾乎不受限制的權(quán)限,并可使用系統(tǒng)分區(qū)和供應(yīng)商分區(qū)中的輸入腳本在啟動(dòng)過(guò)程中初始化系統(tǒng)洗鸵。該訪問(wèn)權(quán)限會(huì)導(dǎo)致 Treble 系統(tǒng)/供應(yīng)商拆分中出現(xiàn)巨大漏洞悴侵,因?yàn)楣?yīng)商腳本可能會(huì)指示 init 訪問(wèn)不屬于穩(wěn)定系統(tǒng)-供應(yīng)商 ABI(應(yīng)用二進(jìn)制接口)的文件、屬性等。
供應(yīng)商 init 已設(shè)計(jì)為使用單獨(dú)的安全增強(qiáng)型 Linux (SELinux) 域 vendor_init
欣喧,以利用供應(yīng)商專屬權(quán)限來(lái)運(yùn)行 /vendor
中的命令歹撒,從而填補(bǔ)此漏洞。
<devsite-heading text="機(jī)制" for="mechanism" level="h2" link="" toc="" class="" back-to-top="">## 機(jī)制</devsite-heading>
<devsite-heading text="機(jī)制" for="mechanism" level="h2" link="" toc="" class="" back-to-top=""></devsite-heading>
供應(yīng)商 init 會(huì)在啟動(dòng)過(guò)程的早期派生在 SELinux 環(huán)境 u:r:vendor_init:s0
中運(yùn)行的 init 子進(jìn)程看疗。此 SELinux 環(huán)境具有的權(quán)限明顯少于默認(rèn) init 環(huán)境沙峻,并且其訪問(wèn)權(quán)限僅限于供應(yīng)商專用或?qū)儆诜€(wěn)定系統(tǒng)-供應(yīng)商 ABI 的文件、屬性等两芳。
Init 會(huì)檢查它加載的每個(gè)腳本以查看其路徑是否以 /vendor
開(kāi)頭摔寨,如果是,則添加標(biāo)記以指示其命令必須在供應(yīng)商 init 環(huán)境中運(yùn)行怖辆。每個(gè)內(nèi)置 init 都使用布爾值進(jìn)行注釋是复,該布爾值指定是否必須在供應(yīng)商 init 子進(jìn)程中運(yùn)行相應(yīng)命令:
- 訪問(wèn)文件系統(tǒng)的大多數(shù)命令都被注釋為在供應(yīng)商 init 子進(jìn)程中運(yùn)行,因此受供應(yīng)商 init SEPolicy 的約束竖螃。
- 大多數(shù)會(huì)影響內(nèi)部 init 狀態(tài)的命令(例如淑廊,啟動(dòng)和停止服務(wù))都在普通 init 進(jìn)程中運(yùn)行。這些命令能獲知供應(yīng)商腳本正在調(diào)用它們來(lái)處理它們自己的非 SELinux 權(quán)限特咆。
Init 的主處理循環(huán)包含一項(xiàng)檢查季惩,以檢查是否會(huì)發(fā)生以下情況:如果某個(gè)命令被注釋為在供應(yīng)商子進(jìn)程中運(yùn)行并且源自供應(yīng)商腳本,則系統(tǒng)會(huì)通過(guò)進(jìn)程間通信 (IPC) 將該命令發(fā)送到供應(yīng)商 init 子進(jìn)程,然后這個(gè)子進(jìn)程會(huì)運(yùn)行該命令并將結(jié)果發(fā)送回 init画拾。
<devsite-heading text="使用供應(yīng)商 init" for="using-vendor-init" level="h2" link="" toc="" class="" back-to-top="">## 使用供應(yīng)商 init</devsite-heading> <devsite-heading text="使用供應(yīng)商 init" for="using-vendor-init" level="h2" link="" toc="" class="" back-to-top=""></devsite-heading>
供應(yīng)商 init 默認(rèn)處于啟用狀態(tài)啥繁,其限制適用于 /vendor
分區(qū)中存在的所有 init 腳本。對(duì)于其腳本尚未訪問(wèn)系統(tǒng)專用文件青抛、屬性等的供應(yīng)商旗闽,供應(yīng)商 init 應(yīng)該是透明的。
但是脂凶,如果給定供應(yīng)商腳本中的命令違反了供應(yīng)商 init 限制宪睹,則這些命令將無(wú)法運(yùn)行。如果命令運(yùn)行失敗蚕钦,系統(tǒng)會(huì)在 init 內(nèi)核日志中記錄一行(可通過(guò) dmesg 查看)來(lái)指示其運(yùn)行失敗亭病。因 SELinux 政策限制而運(yùn)行失敗的任何命令都會(huì)伴有 SELinux 審核。包含 SELinux 審核的失敗示例如下:
<devsite-code no-copy=""><pre class="" is-upgraded="">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</pre></devsite-code>
如果某個(gè)命令運(yùn)行失敗嘶居,則有兩種選擇:
- 如果該命令是因既有限制而運(yùn)行失斪锾(例如,如果該命令訪問(wèn)的是系統(tǒng)文件或?qū)傩裕┯势ǎ瑒t必須以適合 Treble 的方式重新實(shí)現(xiàn)該命令整袁,并僅采用穩(wěn)定的接口。Neverallow 規(guī)則禁止添加訪問(wèn)不屬于穩(wěn)定系統(tǒng)-供應(yīng)商 ABI 的系統(tǒng)文件的權(quán)限佑吝。
- 如果 SELinux 標(biāo)簽是新的且尚未在系統(tǒng)
vendor_init.te
中為其授予權(quán)限坐昙,也未通過(guò) neverallow 規(guī)則為其排除權(quán)限,則可以在設(shè)備專用vendor_init.te
中為這個(gè)新標(biāo)簽授予權(quán)限芋忿。
對(duì)于搭載 Android 9 之前版本的設(shè)備炸客,可以通過(guò)將 data_between_core_and_vendor_violators
類型屬性添加到設(shè)備專用 vendor_init.te
文件來(lái)繞過(guò) neverallows 規(guī)則。
<devsite-heading text="代碼位置" for="code-locations" level="h2" link="" toc="" class="" back-to-top="">## 代碼位置</devsite-heading>
<devsite-heading text="代碼位置" for="code-locations" level="h2" link="" toc="" class="" back-to-top=""></devsite-heading>
供應(yīng)商 init IPC 的大部分邏輯都位于 system/core/init/subcontext.cpp 中戈钢。
命令表位于 system/core/init/builtins.cpp 中的 BuiltinFunctionMap
類中痹仙,其中包含用于指示是否必須在供應(yīng)商 init 子進(jìn)程中運(yùn)行相應(yīng)命令的注釋。
供應(yīng)商 init 的 SEPolicy 已被拆分到 system/sepolicy 中的私有目錄 (system/sepolicy/private/vendor_init.te) 和公共目錄 (system/sepolicy/public/vendor_init.te)殉了。