RFC-0206:淘汰 stash | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 淘汰 stash 服務,並遷移用戶端以使用儲存空間能力 |
問題 | |
Gerrit 變更 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2022-12-08 |
審查日期 (年-月-日) | 2022-01-13 |
摘要
Stash 服務未維護,且目前的實作方式無法提供最初建立的屬性。這份 RFC 建議淘汰 stash。我們會將使用 stash 的用戶端遷移至 Fuchsia 的標準持續性儲存空間功能,然後刪除提供 stash 服務的三個元件。
提振精神
Stash 是一種簡單的持久性服務,最初是為了讓需要在開機程序 (通常是在軟體更新前) 早期存取持久性可變狀態的平台元件使用。
如以下所述,Stash 通訊協定有三種變化版本。所有變化版本都使用相同的基礎 FIDL 通訊協定,並使用相同的二進位檔實作。本文件使用「stash」一詞涵蓋所有這些變化版本。
每次 Fuchsia 在軟體更新前讀取永久可變狀態,都可能讓攻擊者有機會保留存取權:如果攻擊者在先前的電源週期中取得裝置的完整控制權,我們必須假設他們能夠將任意資料寫入裝置的永久可變狀態。讀取可變資料的程式碼路徑中存在漏洞,可能會讓攻擊者控制的資料在下一個電源週期中攻擊系統。如果讀取作業發生在開機程序的早期,後果可能更嚴重;攻擊者可能會阻止軟體更新,進而防止安全漏洞修補。
Stash 旨在提供簡單且安全的持續性可變儲存空間,以便在早期啟動時使用,進而降低這種情況的風險。Stash 原本應具備以下三個屬性:
- 最小化:Stash 應使用比完整儲存空間堆疊更小、更簡單的程式碼庫,讓實作更容易審查,並降低發生錯誤的風險。
- 易於使用:Stash 應可讓客戶輕鬆使用,降低與持續性可變狀態整合時發生錯誤的風險。
- 安全:由於 stash 的存在目的是提升系統安全性,因此其設計和實作方式不應引入新的安全性問題。
目前 stash 無法提供下列大部分的屬性:
- 最小化 - Stash 是以 FIDL 伺服器的形式實作,位於序列化層之上,而序列化層位於標準檔案系統之上 (位於 zxcrypt 之上的 fxfs 或 minfs)。Stash 並沒有比標準儲存空間堆疊更簡單。理論上,日後可以不變更 FIDL 介面,改用更簡單的儲存空間實作方式,但我們目前沒有這類計畫。
- 易於使用:Stash 主要符合這項目標。其 FIDL 介面會公開簡單的鍵/值模式,並提供有限數量的資料類型。這可讓用戶端程式碼保持簡單,並降低用戶端程式碼中的錯誤機率。需要處理回溯相容性、交易寫入和 FIDL 錯誤,確實會帶來一些複雜性,而且在某些情況下,用戶端仍需要編寫自己的輔助程式庫,例如 wlan。
- 安全:Stash 假設元件架構的設計會提供用戶端身分,讓 FIDL 伺服器識別其用戶端。元件架構不會提供用戶端身分,且目前也沒有在可預見的未來推出這項功能的計畫。這表示不同的 stash 用戶端可以讀取及寫入彼此的資料,而通訊協定則是依靠榮譽制度來避免這種情況。
雖然 stash 最初只打算支援「早期啟動」元件,但 Fuchsia 並未正式定義早期啟動階段,也沒有列出哪些元件屬於「早期啟動」元件。部分儲藏室用戶端不會在啟動程序初期啟動,且沒有任何現有用戶端會在啟動期間啟動。
自 2020 年起,Fuchsia 已管理複雜的重複和隔離系統,以解決上述安全性問題 (請參閱 https://fxbug.dev/42124367)。
- 已定義三種不同的 FIDL 暫存協定:
fuchsia.stash.Store
、fuchsia.stash.Store2
和fuchsia.stash.SecureStore
。 - 有三個不同的 stash 元件,每個元件都會以獨立程序執行,並提供獨立的通訊協定。
- Stash 用戶端會謹慎指派至三種通訊協定之一,並評估共用管道的用戶端,確保彼此讀取或寫入資料的風險可接受。
- 因此,我們建立了 BUILD 可見性清單,以免在未經安全性審查的情況下新增新的 stash 用戶端。
這種情況會導致持續的混淆和工程成本,而效能和安全性屬性幾乎不足以應付。
相關人員
協助人員:
- hjfreyer
審查者:
- atait (DHCP)
- brunodalbo (網路堆疊)
- ecstone (遷移)
- emircan (Scenic)
- jamuraa (藍牙)
- nmccracken (WLAN)
- palmer (安全性)
- senj (Omaha Client)
- paulfaria (設定服務)
諮詢:
- silberst, wittrock, shayba, cgonyeo, erahm, mnck, jfsulliv
社會化:
我們與所有受影響客戶的利益相關者合作,共同擬定這份 RFC 的早期草稿。
設計
我們打算淘汰 stash,並將大部分現有用戶端遷移至其他元件使用的 "資料"儲存空間功能。儲存空間功能可透過標準檔案系統 API 存取。對於大多數元件,這項遷移作業會使用序列化程式庫,將元件的持續性資料結構轉換為位元組串流,然後由元件寫入磁碟。讀取永久性資料時,系統會從磁碟讀取檔案,然後使用相同的程式庫將元件的永久性資料結構進行反序化並填入。
Scenic 並未將 stash 用於預期用途 (參見 https://fxbug.dev/42173164),我們會將其用途遷移至結構化設定開發人員覆寫值。
建議您盡可能減少在開機初期啟動,且可能影響軟體更新成功率的元件攻擊面積。目前依賴 stash 的網路和 SWD 元件應謹慎使用資料儲存空間能力,但我們不會為這些元件維護一組獨立的儲存空間存取權要求。將資料安全地儲存在儲存空間能力中的最佳做法包括:
- 盡量減少要保存的資料量。
- 使用精確且明確定義的資料類型。
- 使用經過安全性審查的序列化程式庫來封裝及解開資料。
此設計可根據所需的儲藏室屬性進行評估,如下所示:
- 最小化:整體複雜度與現況相似:仍會使用序列化程式庫 (但使用方式會從一般位置改為每個用戶端)。Fxfs (或 minfs 和 zxcrypt) 仍會存在。日後仍可透過更簡單的檔案系統支援儲存空間能力,但這可能需要在用戶端中進行變更。
- 易於使用:易用性與現況相似:用戶端必須與序列化程式庫互動,並執行基本的檔案系統作業,而非管理 FIDL 連線、交易和失敗。目前有幾種使用儲存空間能力保留 Fuchsia 元件狀態的現有實作方式,這些實作方式可重複使用。
- 安全性:強化安全性:設計可確保元件之間的隔離。我們使用的是已通過安全性審查,且已在正式環境中使用的現有 Fuchsia 技術。
此外,這項設計也改善了其他幾項屬性:
- 移除三個元件執行個體後,資源使用率降低
- 更容易將磁碟使用率歸因於使用該磁碟的元件
實作
如果這項提案獲得核准,我們會明確將 stash 元件和所有 stash 通訊協定標示為已淘汰。
接著,我們會與七個受影響的客戶元件合作,達成遷移計畫和大致時間表的共識。在某些情況下,團隊已計劃從 stash 遷移 (例如 https://fxbug.dev/42172963),在其他情況下,信任的平台服務團隊可以協助進行遷移。這份 RFC 並未指定完成遷移作業的期限。
在暫存區中儲存重要資料的元件需要透過中繼版本才能完成遷移作業 (也就是每部裝置在軟體升級程序中必須經過的軟體版本)。在這個中繼版本中,元件可從儲存或儲存空間能力讀取其持續性狀態,但會寫入儲存空間能力。經過這個踏腳石後,系統會確保在元件移除讀取暫存資料的程式碼前,先將資料遷移至儲存空間能力。
我們會與 Stash 客戶合作,規劃遷移作業,並盡量減少所需的平台踏板版本數量。
特定 stash 通訊協定的所有用戶端完成遷移後,系統就會刪除該通訊協定和服務該通訊協定的 stash 例項。Stash 二進位檔會與最後一個通訊協定一併刪除。
成效
這項提案會刪除三個元件執行個體,以降低磁碟、記憶體和 CPU 使用率。
安全性考量
這項提案可提高 Fuchsia 的安全性,因為它可確保早期啟動元件不再能讀取及寫入彼此的持續性狀態,並可排除目前未維護的程式碼。
隱私權注意事項
這項提案不會變更收集及儲存的使用者資料組合。隱私權方面稍有改善,因為遭到入侵的早期啟動元件無法再讀取其他元件儲存的 PII 資料。
測試
現有的端對端測試和整合測試涵蓋使用 stash 儲存及擷取持續可變狀態的情況。這些相同的測試會涵蓋使用基本儲存空間能力儲存及擷取此狀態的情況。每個 Stash 用戶端都應新增整合測試,驗證資料從 Stash 遷移至儲存空間能力。
說明文件
遷移完成後,系統會刪除現有的 Stash 文件。
考慮的替代方案
替代方案 1:使用新的「基本」儲存空間能力
目前的提案建議使用現有的「資料」儲存空間能力。類似的解決方案是建立新的「基本」儲存空間,專供早期啟動元件使用。
使用個別的儲存空間能力,可讓我們追蹤最終應使用較簡單儲存空間解決方案的元件。使用「基本」儲存空間能力的元件會遵循一套最佳做法,以降低複雜度、減少錯誤風險,並簡化遷移至日後替代後端的程序。最佳做法可能包括:
- 使用核准的序列化程式庫來封裝及解封裝資料。例如,Rust 元件的 serde
- 以原子方式更新檔案內容。例如,寫入臨時檔案,然後將臨時檔案重新命名為最終路徑
- 請勿建立子目錄
- 請勿建立大於 X KB 的檔案
- 請勿建立超過 Y 個檔案
這些最佳做法中的許多內容都會納入簡化程序,我們可以在替換的檔案系統中進行這項程序,以支援「基本」儲存空間能力。舉例來說,如果用戶端不使用目錄,則遷移至不支援目錄的簡單檔案系統會比較容易。
安全性團隊會維護一份清單,列出哪些元件屬於「早期啟動」類別。自動化工具會驗證這些元件是否只使用「基本」儲存空間能力,並在可行情況下,驗證這些元件對檔案系統的使用方式是否符合最佳做法。
這項解決方案的初始導入作業很簡單:「basic」可由現有「data」fxfs 或 minfs 分割區的新子目錄支援。不過,您必須付出大量程序和工具成本,才能維持一致的「早期啟動」定義,並建立工具,在這些早期啟動元件中強制執行資料持續性模式。
Fuchsia 不打算實作更簡單的檔案系統,以支援「基本」儲存空間能力。若沒有不同的檔案系統,花費資源維護由相同實作項目支援的兩組不同用戶端,並不會帶來太多好處,因此我們並未選取這項解決方案。
替代方案 2:為早期可變化狀態編寫專用用戶端程式庫
目前的提案建議使用現有的成熟程式庫,將可變動的持久狀態序列化。另一種做法是在每種目標語言 (目前為 Rust 和 Go,未來某個時間點可能會是 C++) 中編寫新的用戶端程式庫。
專用的用戶端程式庫可以輕鬆強制執行最佳做法,且比現有的通用序列化程式庫 (例如 serde) 更小巧且更易於使用。不過,設計及實作這些新程式庫會大幅提高此提案的工程成本。現有的用戶端會使用 stash 來執行不同用途,並搭配不同的包裝函式,因此單一用戶端程式庫可能無法滿足所有用戶端的需求。Stash 目前沒有人力,如果要設計及實作新的用戶端程式庫,可能會導致遷移作業延後數季。