| RFC-0206:淘汰 Stash | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 淘汰 Stash 服務,並將用戶端遷移至儲存空間能力 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2022-12-08 |
| 評論日期 (年-月-日) | 2022-01-13 |
摘要
暫存服務未維護,且目前的實作方式無法提供最初建立時要提供的屬性。這項 RFC 提議淘汰 stash。我們會將使用 stash 的用戶端遷移至 Fuchsia 的標準永久儲存空間功能,然後刪除提供 stash 服務的三個元件。
提振精神
Stash 是一項簡單的持續性服務,最初是為了讓平台元件在啟動程序初期 (通常是在軟體更新前) 存取持續性可變狀態而建立。
如下文所述,stash 通訊協定有三種不同的變體。所有變化版本都使用相同的基礎 FIDL 通訊協定,並使用相同的二進位檔實作。本文使用「stash」一詞涵蓋所有這些變體。
每次 Fuchsia 在軟體更新前讀取永久可變狀態時,攻擊者都有可能持續存取:如果攻擊者在先前的電源週期中完全控制裝置,我們必須假設他們能夠將任意資料寫入裝置的永久可變狀態。如果讀取可變動資料的程式碼路徑有安全漏洞,攻擊者控制的資料可能會在下次電源週期中入侵系統。如果讀取作業在啟動程序初期發生,後果可能會更嚴重;攻擊者可能會阻止軟體更新,進而防止安全漏洞獲得修補。
Stash 的設計目的是提供簡單、安全、可變動的永久儲存空間,用於提早啟動,降低這種情況的風險。Stash 應有三個屬性:
- 精簡:Stash 應使用比完整儲存空間堆疊更小、更簡單的程式碼集,以便審查實作方式,並降低錯誤風險。
- 容易使用:Stash 應易於用戶端使用,降低與永久可變狀態整合時發生錯誤的風險。
- 安全:由於 Stash 的存在是為了提升系統安全性,因此其設計和實作不應帶來新的安全性問題。
目前 stash 無法提供下列大部分屬性:
- Minimal:Stash 是以 FIDL 伺服器的形式實作,位於序列化層之上,而序列化層則位於標準檔案系統之上 (zxcrypt 之上的 fxfs 或 minfs)。Stash 的複雜度與標準儲存空間堆疊相當。理論上,未來可以遷移至更簡單的儲存空間實作,而不必變更 FIDL 介面,但目前沒有這項計畫。
- 簡單易用:Stash 主要符合這項目標。其 FIDL 介面會公開簡單的鍵/值範例,其中包含有限數量的資料類型。這可讓用戶端程式碼保持簡單,並降低用戶端程式碼發生錯誤的可能性。處理回溯相容性、交易寫入和 FIDL 錯誤的需求確實會增加一些複雜度,而且在某些情況下,用戶端仍需編寫自己的輔助程式庫,例如 wlan。
- 安全:stash 的設計假設元件架構會提供用戶端身分,讓 FIDL 伺服器識別用戶端。元件架構不提供用戶端身分,且在可預見的未來,也沒有導入這項功能的計畫。這表示不同的 Stash 用戶端可以讀取及寫入彼此的資料,而通訊協定則仰賴榮譽制度來避免這種情況。
雖然 stash 最初僅用於支援「提早啟動」元件,但 Fuchsia 並未正式定義提早啟動階段,也沒有列出哪些元件屬於「提早啟動」。stash 的多個用戶端不會在啟動程序初期啟動,且現有用戶端都不會在啟動程序期間啟動。
自 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 (Security)
- senj (Omaha 用戶端)
- paulfaria (設定服務)
諮詢對象:
- silberst, wittrock, shayba, cgonyeo, erahm, mnck, jfsulliv
社交:
這份 RFC 的早期草稿是與所有受影響用戶端的利害關係人合作開發。
設計
我們打算淘汰 stash,並將大部分現有用戶端遷移至其他元件使用的「資料」儲存空間能力。儲存空間能力可透過標準檔案系統 API 存取。對大多數元件來說,這項遷移作業會使用序列化程式庫,將元件的永久資料結構轉換為位元組串流,然後元件會將這些串流寫入磁碟。讀取永久資料時,系統會從磁碟讀取檔案,然後使用相同的程式庫,將元件的永久資料結構反序列化並填入。
Scenic 未將 Stash 用於預期用途 (參考資料:https://fxbug.dev/42173164),我們會將其用途遷移至結構化設定開發人員覆寫。
建議您盡可能縮小在啟動初期啟動的元件攻擊面,這可能會影響軟體更新的成功率。目前依賴 stash 的網路和 SWD 元件應謹慎使用資料儲存空間能力,但我們不會為這些元件維護另一組儲存空間存取權規定。如要安全地將資料永久儲存至儲存空間能力,最佳做法包括:
- 盡可能減少保存的資料量。
- 使用範圍狹窄且定義精確的資料類型。
- 使用經過安全性審查的序列化程式庫,封裝及解壓縮資料。
這項設計可根據理想的 Stash 屬性進行評估,如下所示:
- 極小:整體複雜度與現狀類似,仍會使用序列化程式庫 (但使用方式從一般位置移至各個用戶端)。Fxfs (或 minfs 和 zxcrypt) 仍會保留。日後仍可透過更簡單的檔案系統支援儲存空間能力,但可能需要變更用戶端。
- 易於使用:易用性與現狀類似,用戶端必須與序列化程式庫互動,並執行基本檔案系統作業,而非管理 FIDL 連線、交易和失敗。目前有幾種實作方式,可使用儲存空間能力保留 Fuchsia 元件狀態,而且這些實作方式可以重複使用。
- 安全性 - 安全性提升:設計可確保元件之間相互隔離。我們使用已通過安全性審查,且已用於正式環境的現有 Fuchsia 技術。
此外,這項設計也改善了其他幾項屬性:
- 由於我們移除了三個元件執行個體,資源使用率會降低
- 更容易將磁碟使用率歸因於使用磁碟的元件
實作
如果這項提案通過,我們會明確記錄 stash 元件和所有 stash 通訊協定已淘汰。
接著,我們會與七個受影響的用戶端元件合作,共同制定遷移計畫和大致時間表。在某些情況下,團隊已計劃從 stash 遷移 (例如 https://fxbug.dev/42172963),在其他情況下,信任的平台服務團隊可以協助遷移。這份 RFC 未指定完成遷移的期限。
如果元件將重要資料儲存在暫存區,則需要過渡版本才能完成遷移 (即每部裝置在軟體升級過程中都必須經過的軟體版本)。在這個過渡版本中,元件可以從暫存區或儲存空間能力讀取其永久狀態,但會寫入儲存空間能力。透過這個過渡階段,可確保資料先遷移至儲存空間能力,元件再移除讀取暫存區的程式碼。
我們與 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 目前沒有人員,如果致力於設計及實作新的用戶端程式庫,可能會導致遷移作業延遲數季。