驗證啟動

「已驗證開機」功能會先以密碼編譯方式驗證所有可執行程式碼和資料,確認屬於要啟動的 Android 版本,才會使用這些程式碼和資料。包括核心 (從 boot 分區載入)、裝置樹狀結構 (從 dtbo 分區載入)、system 分區、vendor 分區等。

通常會將 bootdtbo 等小型分割區的完整內容載入記憶體,然後計算其雜湊值,藉此驗證這些分割區 (這些分割區只會讀取一次)。接著,系統會將計算出的雜湊值與預期雜湊值進行比較。如果值不相符,Android 將不會載入。 詳情請參閱「啟動流程」。

如果分割區過大而無法放入記憶體 (例如檔案系統),則可使用雜湊樹狀結構,在資料載入記憶體時持續進行驗證。在本例中,系統會在執行階段計算雜湊樹狀結構的根雜湊,並與預期的根雜湊值進行比較。Android 包含 dm-verity 驅動程式,可驗證較大的分割區。如果計算出的根雜湊值在某個時間點與預期的根雜湊值不符,系統就不會使用該資料,且 Android 會進入錯誤狀態。詳情請參閱「dm-verity 損毀」。

預期雜湊通常會儲存在每個已驗證分區的結尾或開頭,或是專屬分區中,或同時儲存在這兩處。最重要的是,這些雜湊是由信任根直接或間接簽署。舉例來說,AVB 實作方式同時支援這兩種做法,詳情請參閱「Android 驗證開機」。

復原保護措施

即使更新程序完全安全,非持續性 Android 核心漏洞仍可能手動安裝舊版 Android (較容易受到攻擊),然後重新啟動至該版本,並使用該版本安裝持續性漏洞。從此攻擊者就永久擁有裝置,可以執行任何操作,包括停用更新。

防範這類攻擊的機制稱為「回溯保護」。通常會使用防竄改儲存空間記錄最新的 Android 版本,如果 Android 版本低於記錄的版本,則拒絕啟動 Android,藉此實作回溯保護機制。版本通常會以每個分區為單位進行追蹤。

如要進一步瞭解 AVB 如何處理回溯保護機制,請參閱 AVB README

處理驗證錯誤

驗證可能會在開機時失敗 (例如,如果 boot 分割區上計算出的雜湊與預期雜湊不符),或在執行階段失敗 (例如,如果 dm-verity 在 system 分割區上遇到驗證錯誤)。如果開機時驗證失敗,裝置就無法開機,使用者必須按照步驟復原裝置。

如果驗證在執行階段失敗,流程會稍微複雜一些。如果裝置使用 dm-verity,則應以 restart 模式設定。在 restart 模式下,如果發生驗證錯誤,裝置會立即重新啟動,並設定特定標記來指出原因。開機載入程式應會注意到這個標記,並將 dm-verity 切換為使用 I/O 錯誤 (eio) 模式,且會維持這個模式,直到安裝新更新為止。

以「eio」模式啟動時,裝置會顯示錯誤畫面,告知使用者系統偵測到損毀,裝置可能無法正常運作。畫面會持續顯示,直到使用者關閉為止。在 eio 模式下,如果發生驗證錯誤,dm-verity 驅動程式不會重新啟動裝置,而是會傳回 EIO 錯誤,應用程式必須處理這項錯誤。

目的是讓系統更新程式執行 (因此可以安裝沒有損毀錯誤的新 OS),或讓使用者盡可能從裝置中取出資料。安裝新 OS 後,開機載入器會注意到新安裝的 OS,並切換回 restart 模式。