供應商初始化

初始化程序幾乎不受任何權限限制,並使用系統和供應商分割區的輸入指令碼,在開機程序中初始化系統。這項存取權會在 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 預設為啟用,且其限制會套用至 /vendor 分區中的所有 init 指令碼。如果供應商的指令碼目前未存取系統專屬檔案、屬性等,供應商應可順利完成供應商 init 轉換。

不過,如果特定供應商指令碼中的指令違反供應商初始化限制,指令就會失敗。如果指令失敗,核心記錄 (可透過 dmesg 查看) 中會有一行來自 init 的訊息,指出失敗。如果指令因 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 推出前發布,只要在裝置專屬的 vendor_init.te 檔案中加入 data_between_core_and_vendor_violators 型別屬性,即可略過 neverallows 規則。

程式碼位置

供應商 init IPC 的大部分邏輯位於 system/core/init/subcontext.cpp

指令表位於 system/core/init/builtins.cppBuiltinFunctionMap 類別中,並包含註解,指出指令是否必須在供應商 init 子程序中執行。

供應商 init 的 SEPolicy 分別位於 system/sepolicy 中的私有 (system/sepolicy/private/vendor_init.te) 和公開 (system/sepolicy/public/vendor_init.te) 目錄。