RFC-0206:淘汰停滯

RFC-0206:淘汰 Stash
狀態已接受
區域
  • 安全性
  • 儲存空間
說明

淘汰 Stash 服務,並將用戶遷移至儲存空間能力

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2022-12-08
審查日期 (年-月-日)2022-01-13

摘要

Stash 服務已停止維護,且目前的實作方式無法提供最初建立時的屬性。這項 RFC 建議停用暫存。我們會將使用 stash 的用戶端遷移至 Fuchsia 的標準永久儲存功能,然後刪除提供 stash 服務的三個元件。

提振精神

Stash 是一種簡單的持續性服務,最初是為平台元件而建立,這些元件需要在啟動程序初期 (通常是在軟體更新之前),存取持續性可變動狀態。

如下文詳述,stash 通訊協定有三種不同變體。所有變體都使用相同的基礎 FIDL 通訊協定, 並使用相同的二進位檔實作。本文使用「隱藏」一詞涵蓋所有這些變體。

每次 Fuchsia 在軟體更新前讀取可變動的持續性狀態,都可能讓攻擊者有機會持續存取裝置:如果攻擊者在先前的電源週期中完全掌控裝置,我們必須假設他們能夠將任意資料寫入裝置的可變動持續性狀態。讀取可變動資料的程式碼路徑存在安全漏洞,可能會讓攻擊者控制的資料在下一個電源週期中利用系統。如果讀取作業在啟動程序初期發生,後果可能更加嚴重;攻擊者可能因此阻止軟體更新,進而避免安全漏洞遭到修補。

Stash 的目的是提供簡單且安全的持續性可變動儲存空間,供早期啟動時使用,藉此降低這種情況的風險。Stash 預計有三項屬性:

  1. 極簡 - Stash 應使用比完整儲存堆疊更小且更簡單的程式碼集,方便審查實作內容,並降低發生錯誤的風險。
  2. 易於使用 - Stash 應易於供用戶端使用,減少與持續性可變動狀態整合時發生錯誤的風險。
  3. 安全:stash 的存在是為了提升系統安全性,因此設計和實作不應造成新的安全問題。

目前 stash 無法提供大部分這些屬性:

  1. 最少 - Stash 會實作 FIDL 伺服器,位於序列化層上方,而序列化層又位於標準檔案系統上方 (fxfs 或 minfs,位於 zxcrypt 上方)。Stash 的複雜程度與標準儲存堆疊不相上下。從理論上來說,日後可以遷移至較簡單的儲存空間實作方式,而不必變更 FIDL 介面,但目前沒有這方面的計畫。
  2. 易於使用 - Stash 主要就是為了達成這個目標。其 FIDL 介面會公開簡單的鍵/值範例,但資料類型數量有限。這項做法可讓用戶端程式碼保持簡單,並降低用戶端程式碼發生錯誤的可能性。處理回溯相容性、交易寫入和 FIDL 錯誤的需求確實會帶來一些複雜性,而且在某些情況下,用戶端仍需編寫自己的輔助程式庫,例如 wlan
  3. 安全 - 隱藏設計假設元件架構會提供用戶端身分,讓 FIDL 伺服器識別用戶端。元件架構不會提供用戶端身分,而且近期內也沒有導入這項功能的計畫。也就是說,不同的暫存用戶端可以讀取及寫入彼此的資料,而通訊協定依賴榮譽制度來避免這種情況。

雖然 stash 最初僅支援「早期啟動」元件,但 Fuchsia 上沒有早期啟動階段的正式定義,也沒有哪些元件屬於「早期啟動」的清單。stash 的多個用戶端不會在啟動程序初期啟動,現有用戶端也不會在啟動程序期間啟動。

自 2020 年起,Fuchsia 採用複雜的複製和隔離系統,解決上述安全性問題 (請參閱 https://fxbug.dev/42124367)。

  • 我們定義了三種不同的 FIDL stash 通訊協定:fuchsia.stash.Storefuchsia.stash.Store2fuchsia.stash.SecureStore
  • 有三種不同的暫存元件,各自以獨立程序執行,並提供獨立的通訊協定。
  • 系統會謹慎地將 Stash 用戶端指派給其中一個通訊協定,並評估共用管道的用戶端,確保讀取或寫入彼此資料的風險可接受。
  • BUILD 可見度清單可防止新增未經過安全審查的 Stash 用戶端。

這種情況導致持續的混淆和工程成本,而其效能和安全屬性僅勉強足夠。

利害關係人

協助人員:

  • hjfreyer

審查者:

  • atait (DHCP)
  • brunodalbo (網路堆疊)
  • ecstone (遷移)
  • emircan (Scenic)
  • jamuraa (藍牙)
  • nmccracken (WLAN)
  • palmer (Security)
  • senj (Omaha Client)
  • paulfaria (設定服務)

已諮詢:

  • silberst、wittrock、shayba、cgonyeo、erahm、mnck、jfsulliv

社交:

這份 RFC 的初稿是與所有受影響用戶端的利害關係人合作開發。

設計

我們打算淘汰暫存功能,並將大部分現有用戶端遷移至其他元件使用的「資料」儲存功能。儲存空間功能是透過標準檔案系統 API 存取。對於大多數元件,這項遷移作業會使用序列化程式庫,將元件的持續性資料結構轉換為位元組串流,然後元件會將這些串流寫入磁碟。讀取永久資料時,需要從磁碟讀取檔案,然後使用相同程式庫還原序列化,並填入元件的永久資料結構。

Scenic 並未將 stash 用於預期用途 (參閱 ref https://fxbug.dev/42173164),我們會將其用途遷移至結構化設定開發人員覆寫

啟動初期啟動的元件可能會影響軟體更新是否成功,因此盡可能減少這類元件的攻擊面是理想做法。目前依賴 stash 的網路和 SWD 元件應謹慎使用資料儲存空間能力,但我們不會為這些元件維護一組獨立的儲存空間存取需求。安全地將資料保存到儲存空間能力的最佳做法包括:

  • 盡量減少保存的資料量。
  • 使用範圍較窄且精確定義的資料類型。
  • 使用經過安全審查的序列化程式庫封裝及解封資料。

您可以根據理想的暫存屬性評估這項設計,如下所示:

  1. 最低 - 整體複雜度與現狀相似:仍會使用序列化程式庫 (但使用方式會從通用位置移至每個用戶端)。Fxfs (或 minfs 和 zxcrypt) 仍存在。日後仍可透過較簡單的檔案系統備份儲存空間能力,但可能需要變更用戶端。
  2. 簡單易用:使用方式與現狀類似,用戶端必須與序列化程式庫互動,並執行基本檔案系統作業,而非管理 FIDL 連線、交易和失敗。目前已有數種實作方式,可使用儲存空間能力保存 Fuchsia 元件狀態,這些實作方式可以重複使用。
  3. 安全性 - 安全性提升:設計可確保元件之間的隔離。我們使用現有的 Fuchsia 技術,這些技術已通過安全性審查,並已用於正式版。

此外,新設計也改善了其他幾項屬性:

  • 移除三個元件執行個體後,資源使用率會降低
  • 現在更容易將磁碟使用率歸因於使用該磁碟的元件

實作

如果這項提案通過,我們會清楚記錄 Stash 元件,並將所有 Stash 通訊協定標示為已淘汰。

接著,我們會與七個受影響的用戶端元件分別合作,商定遷移計畫和預估時間表。在某些情況下,團隊已規劃要從 stash 遷移 (例如 https://fxbug.dev/42172963),在其他情況下,可信的平台服務團隊可以協助遷移。這份 RFC 並未指定完成遷移作業的期限。

在 stash 中儲存重要資料的元件需要透過過渡版本完成遷移 (也就是裝置在軟體升級程序中必須經過的軟體版本)。在這個里程碑,元件可以從暫存或儲存空間能力讀取持續性狀態,但會寫入儲存空間能力。通過這個踏腳石可確保資料遷移至儲存能力,然後元件才會移除讀取暫存檔的程式碼。

我們與 Stash 客戶合作規劃遷移作業時,會盡量減少所需的平台過渡版本數量。

特定暫存通訊協定的所有用戶端完成遷移後,系統就會刪除該通訊協定和提供服務的暫存執行個體。stash binary 會與最後一個通訊協定一併刪除。

效能

這項提案會刪除三個元件執行個體,藉此降低磁碟、記憶體和 CPU 使用率。

安全性考量

這項提案可確保早期啟動元件不再能讀取及寫入彼此的持續性狀態,並淘汰目前未維護的程式碼,進而提升 Fuchsia 的安全性。

隱私權注意事項

這項提案不會改變收集及儲存的使用者資料集。 隱私權獲得小幅提升,因為遭入侵的早期啟動元件無法再讀取其他元件儲存的 PII 資料。

測試

現有的端對端測試和整合測試涵蓋使用 Stash 儲存及擷取可變動的持續性狀態。這些測試也會涵蓋使用基本儲存空間能力儲存及擷取此狀態。每個暫存用戶端都應新增整合測試,以驗證資料從暫存到儲存空間能力的遷移作業。

說明文件

遷移完成後,現有的 Stash 說明文件就會遭到刪除。

考慮的替代方案

替代方案 1:使用新的「基本」儲存空間能力

目前的提案建議使用現有的「資料」儲存空間能力。類似的解決方案是建立新的「基本」儲存空間,專供早期啟動元件使用。

使用獨立的儲存空間能力,有助於追蹤最終應採用較簡單儲存空間解決方案的元件。使用「基本」儲存空間能力的元件會遵循一組最佳做法,以減少複雜度、降低錯誤風險,並簡化遷移至未來替代後端的作業。最佳做法可能包括:

  • 使用核准的序列化程式庫封裝及解封裝資料。例如,Rust 元件的 serde
  • 以不可分割的方式更新檔案內容。例如,先寫入臨時檔案,然後將臨時檔案重新命名為最終路徑
  • 請勿建立子目錄
  • 請勿建立大於 X KB 的檔案
  • 請勿建立超過 Y 個檔案

許多最佳做法都可簡化替代檔案系統,以支援「基本」儲存空間能力。舉例來說,如果用戶端未使用目錄,遷移至不支援目錄的簡單檔案系統就會比較容易。

資安團隊會維護一份清單,列出哪些元件屬於「早期啟動」元件。自動化工具會驗證這些元件是否只使用「基本」儲存空間能力,並盡可能驗證其檔案系統使用方式是否符合最佳做法。

這項解決方案的初始實作程序很簡單:「基本」可由現有「資料」fxfs 或 minfs 分割區上的新子目錄支援。不過,要維持「早期啟動」的一致定義,並建構工具來強制執行這些早期啟動元件中的資料持續性模式,需要投入大量程序和工具成本。

Fuchsia 不打算實作較簡單的檔案系統,以支援「基本」儲存空間能力。如果沒有不同的檔案系統,花費資源維護兩組由相同實作項目支援的用戶端,效益會非常低,因此我們未選擇這個解決方案。

替代方案 2:為早期可變動狀態編寫專屬用戶端程式庫

目前的提案建議使用現有的成熟程式庫,將可變動的持續性狀態序列化。另一種做法是以每種目標語言 (目前為 Rust 和 Go,未來可能包括 C++) 編寫新的用戶端程式庫。

專屬的用戶端程式庫可輕鬆強制執行最佳做法,而且與 serde 等現有的一般用途序列化程式庫相比,體積更小且更容易使用。不過,設計及導入這些新程式庫會大幅增加這項提案的工程成本。現有用戶端會使用 Stash 達成不同目的,並搭配不同包裝函式,因此單一用戶端程式庫可能無法滿足所有這些用戶端的期望。Stash 目前沒有工作人員,如果致力於設計及實作新的用戶端程式庫,可能會延後遷移作業好幾季。

既有技術和參考資料