RFC-0107:動態優惠

RFC-0107:動態優惠
狀態已接受
區域
  • 元件架構
說明

允許在 CFv2 中於執行階段建立方案。

Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2021-05-24
審查日期 (年-月-日)2021-06-24

摘要

在元件架構第 2 版 (CFv2) 中,父項元件可以使用集合,在執行階段將動態子項元件新增至拓撲。不過,無法在執行階段設定提供給這類動態子項元件的功能集。優惠會在父項元件的資訊清單中宣告,且父項元件開始執行後就無法變更。

父項元件的資訊清單會統一處理特定集合中的所有動態子項,甚至無法談論集合中的個別元件。這表示有下列限制:

  1. 無法為個別動態子項提供能力。為集合提供能力,即為該集合中的所有動態子項提供能力。
  2. 您無法將個別動態子項的能力提供給其他元件。從集合提供能力會建立匯總 FIDL 服務,可連線至該集合中的任何動態子項。

本文建議使用動態供應項目,可在執行階段新增至元件拓撲。

利害關係人

  • 在執行階段建構動態拓撲的 CFv2 使用者。他們將由 Driver Framework 團隊代表。
  • 元件架構領域擁有者,可驗證設計是否合理,且不會與任何未來計畫衝突。
  • 安全性,確保這項功能不會破壞系統的安全屬性。

提振精神

大多數 CFv2 用途都涉及元件的靜態拓撲,這些元件會共同運作來完成某些工作。所有這些元件的身分和關係都是預先已知的,而且可以硬式編碼到元件資訊清單中。

在其他一些用途中,開發人員不知道要執行的確切元件集,但知道這些動態元件彼此之間的關係。開發人員可將所有動態元件分組到集合中,特定集合中的每個元件都提供相同的功能組合。

不過,部分 CFv2 使用者想在執行階段建構複雜拓撲,為每個動態子項提供獨特的功能組合,並在動態子項之間提供路由功能。

使用案例:驅動程式即元件

在 Driver Framework 的 Drivers-as-Components 專案中,動態例項化的驅動程式庫元件會依附於其他動態例項化驅動程式庫程式元件提供的功能。我們會將從一個驅動程式庫元件提供給另一個元件的功能,稱為驅動程式庫間功能

CFv2 原生不支援驅動程式庫間的功能。為解決這個問題,Driver Framework 團隊在 driver_manager 中實作了類似能力路徑的功能。這個解決方法有許多缺點,而且會造成驅動程式庫間功能與「正常」功能之間的差異,令人感到困惑:

  • 元件會開啟傳入命名空間中的路徑,藉此連線至「一般」功能,但會透過 Driver-Framework 專屬的 exposed_dir 欄位連線至驅動程式庫間功能。
  • 取得 exposed_dir 後,接收元件即可存取依附元件實作的「所有」通訊協定。driver_manager 不會將接收端的存取權限縮至僅限必要的通訊協定。Driver Framework 團隊可以修正這個問題,但這樣做會進一步複製元件架構機制。
  • 驅動程式元件必須在資訊清單的 use 區段中,宣告所依附的「一般」功能,但不應以相同方式列出驅動程式庫間的功能。如果這樣做,元件管理服務就無法找到 offer 來滿足 use
    • 目前,元件管理服務大多會忽略這些多餘的 use,但這可能會在短期內造成混淆,而且多餘的 use 可能會在長期內變成錯誤。

駕駛人作者不應將「一般」功能視為與驅動程式庫之間的功能不同,因此應盡快移除這項區別。等待時間越長,模型變更時需要遷移的驅動程式就越多。

設計

這項提案會擴充 fuchsia.sys2.Realm/CreateChild API,接受 OfferDecl 清單,說明要提供給新建立子項的其他功能 (超出正常情況下會提供的功能)。我們會將以這種方式指定的 OfferDecl 稱為動態方案。以一般方式指定的 OfferDecl (即列在元件資訊清單中) 則稱為靜態方案

任何類型的方案 (即通訊協定、目錄等) 都可以做為動態方案。

動態優惠一律會以新建立的子項元件為目標。因此,在建立元件時,系統會決定一組指定元件的動態供應項目,之後就無法變更。(OfferDecltarget 欄位是否必須實際指定,將在 API 審查中決定)。

凡是適用於靜態商品的來源,也適用於動態商品。此外,與靜態提案不同,動態提案可以使用「同層級」動態子項元件 (即與目標具有相同父項的元件) 做為來源。如果動態子項是動態方案的來源,目標就不必與來源位於同一個集合。

建立子項元件後,動態供應項目應與靜態供應項目完全相同,包括元件關閉順序等考量。

破壞

動態優惠會在來源或目標遭到毀損時毀損。優惠毀損後,系統的行為會與優惠從未存在時完全相同。

如果可以,動態出價使用者應優先銷毀目標,再銷毀來源。如果目標遭到毀損 (如果提案掉進森林,周圍沒有任何元件聽到),從拓撲中移除提案的程序就微不足道。不過,有時來源會先於目標遭到破壞,這是無可避免的。請注意,使用單次執行集合 (RFC-0101 中導入) 時,動態元件會在終止後立即遭到刪除,而終止時間不確定。

即使是來源遭到破壞,程序也很簡單:

  1. 元件管理工具會關閉來源元件。這可防止目標開啟與來源的任何新連線,並指示執行元件停止來源元件 (如果正在執行)。
  2. 來源元件停止時,來源與目標之間的任何管道都會關閉。
  3. 來源元件和動態優惠會同時從拓撲中移除。

以目標的角度來看,對應能力的管道會關閉,且任何重新取得能力的嘗試都會永久失敗,就像能力一開始就未經過路徑傳送一樣。

這項 RFC 並未提供重新建立這類優惠的機制。

防止依附元件週期

CFv2 規定元件和元件間的強烈提案必須形成有向非循環圖,元件才能依附屬關係順序正常關閉。對於靜態供應項目,我們可以查看元件資訊清單,確保沒有依附元件週期。

如果是動態供應項目,只要符合下列原則,就能確保依附元件圖表沒有週期:

  1. 動態元件的建立順序是嚴格的總順序。換句話說,不會有兩個動態元件在完全相同的時間新增至拓撲。
  2. 動態出價一律會與目標元件同時建立。
  3. 所有優惠 (靜態和動態) 均無法變更。
  4. 所有供應項目 (靜態和動態) 都必須一律具備有效的來源和目標。CreateChild 會在動態建立優惠時檢查這項屬性,且每當來源或目標遭到毀損,優惠也會一併毀損。

綜合來看,這表示動態出價的來源一律比目標舊。如果來源較年輕,表示目標建立時來源不存在,因此優惠在建立時的來源無效。由於「建立順序」是嚴格的總順序,因此不可能出現依附元件週期。

處理無效路徑

撰寫本文時,元件管理服務不會主動拒絕含有無效路徑設定的元件資訊清單。也就是說,如果某個來源提供能力,但未公開該功能,或是元件未收到所用能力的供應項目,系統不會在建立元件時引發錯誤。只有在元件嘗試開啟無效路徑能力時,才會引發錯誤。

秉持「動態優惠應與靜態優惠行為相同」的原則,我們將在此實作相同的行為。元件可能會為來源未公開的能力建立動態供應項目。同樣地,父項元件可能會建立動態子項元件,但不會為使用的每項能力提供供應項目。

日後,如果元件管理服務變更為在這些情況下提早傳回錯誤,我們也會變更 CreateChild 的合約,使其傳回錯誤。

實作

這項異動對使用者來說,主要影響包括:

  1. CreateChild API 進行回溯相容的變更,接受動態優惠清單做為引數。
  2. 每個集合的選擇加入設定,允許動態優惠指定該集合中的元件。(請參閱「安全性考量」一節的討論內容)。
  3. 可選擇加入的父項元件許可清單。(注意:請參閱更新:移除許可清單)

(1) 的實作程序完全在本機的元件管理服務中進行。 實作 (2) 和 (3) 可能需要變更剖析 CML 檔案的工具。無論是哪種情況,都不需要跨團隊協調。

效能

這項異動不會影響系統效能,但對 CreateChildDestroyChild 的呼叫除外,因為這些作業不常執行,且並非效能關鍵作業。即使是這些作業,預期也不會對效能造成負面影響。

人體工學

這項功能是新功能,如果元件的依附元件突然消失,可能會對元件作者造成人體工學方面的挑戰。

從目標元件的角度來看,判斷在提案遭到毀損後發生了什麼事並非完全簡單:它只會看到管道關閉。目標元件無法立即判斷來源元件是否遭到毀損、停止或刻意關閉管道。如要判斷來源是否確實遭到毀損,目標必須嘗試重新連線,並等待元件管理服務傳回表示永久無法路由的訊息。

安全性考量

就本身而言,這項設計會破壞 CFv2 的重要安全目標:所有能力路徑 (或潛在能力路徑) 都應宣告,以便稽核。在測試以外的情況下使用動態優惠時,必須確保可透過元件資訊清單以外的機制稽核潛在能力路徑。

使用這項功能時,Driver Framework 會負責確保潛在能力路徑的空間可供稽核。目前,規則會編碼在多個位置:去中心化繫結規則、主機板驅動程式的原始碼、ACPI,以及其他位置。這使得稽核成為一項挑戰。這個差距並非新問題,需要由 Driver Framework 解決,但如何解決超出本 RFC 的範圍。

CollectionDecl 會新增選擇加入設定,如果有的話,父項元件就能將動態優惠傳遞至該集合中建立的元件。這樣一來,CML 審查人員就能清楚瞭解動態供應項目正在運作,且需要參考元件資訊清單以外的來源,才能瞭解潛在能力路徑的範圍。

此外,元件架構團隊會將選擇加入功能加入許可清單,確保所有用途都適當。(注意:請參閱更新:允許清單移除作業)

之後的作業

如果我們發現更多動態供應項目的用途,可能會在元件資訊清單結構定義中導入供應項目上限。出價上限可用於限制執行階段可建立的動態出價類型。

資訊清單會包含下列陳述:

  • 「通訊協定 fuchsia.example.Foo 可以從元件 A 動態提供給集合 B 中的任何元件」,或
  • 「任何目錄能力都可以在集合 C 中的任意兩個元件之間動態提供」。

在最初的 Driver Framework 用途中,我們認為較粗略的集合層級選擇加入就已足夠。在將任何其他用戶端加入允許清單前,請務必重新評估這項立場。

隱私權注意事項

這項提案不會將系統的任何部分暴露給系統原本無法存取的資料,因此應該不會影響隱私權。

測試

我們會新增單元和整合測試涵蓋範圍,與任何其他 Component Framework 功能類似。Driver Framework 的整合測試會間接提供額外涵蓋範圍。

這項功能既不會協助也不會損害 Component Framework API 的可測試性。使用集合和 Realm 通訊協定時,您必須在整合測試設定中,使用實際的元件管理服務執行個體,這項規定不會改變。

說明文件

由於動態優惠會加入允許清單,且一開始只會由單一用戶端使用,因此高階元件架構概念文件不應更新,提及這項功能的存在。有關 CreateChildDestroyChildCollectionDecl 變更的說明文件應已足夠。

在將任何其他用戶端加入許可清單前,請務必重新評估這項立場。

缺點、替代方案和未知事項

這項設計的主要缺點是,由於並非所有潛在能力路徑都會出現在元件資訊清單中,因此稽核能力路徑會更加複雜。不過,這是驅動程式架構的本質:驅動程式庫元件的拓撲結構本質上是動態的,因為裝置可以隨時從機器新增及移除。靜態優惠顯然不夠,因此故事必須變得更加複雜。動態出價會盡可能模擬靜態出價的行為,盡量減少這項額外的複雜度。

替代方案:功能權杖

先前已有人提議使用功能權杖解決相關問題。該提案可視為這項 RFC 的一般化版本,其中動態供應項目可跨領域。來源元件的父項會「鑄造」能力權杖,並將其傳遞至另一個父項元件 (可能透過一連串的中介元件)。接收元件可將這個權杖傳遞至 CreateChild,做為授權機制,證明雙方家長都同意這項優惠。

建立完成後,動態優惠的行為應與靜態優惠類似,但主要例外是這些動態優惠可以跨運作範圍。靜態提案 (以及主要提案中的動態提案) 一律屬於單一父項元件。

跨領域優惠的影響尚不明確,且我們認為並無必要,因此已拒絕這項選項。

替代方案:提供「即時能力供應商」

fxrev.dev/483166

在主要提案中,動態出價是惰性資料。提案代表元件管理服務應如何將能力要求路徑導向,但提案本身不會提供能力存取權。

我們可以改為傳遞功能供應商,也就是可用於直接取得功能的管道。CreateChild 接著會接受具名能力供應商的向量。動態子元件嘗試開啟動態提供的能力時,該Open要求會轉送至能力供應商。

父項元件可以透過下列方式取得這類能力提供者:

  • 自行實作能力供應器,
  • 呼叫 Realm API,取得其中一個父項或子項公開功能的供應商,或
  • 透過管道從其他元件接收能力供應商。

這會解鎖與能力權杖相同的使用案例,但額外的好處 (或可爭議的缺點) 是,家長可以直接將能力供應器提供給孩子:只要在記憶體中啟動伺服器,並將能力供應器傳遞至 CreateChild 即可。

不過,能力提供者與 CFv2 路由架構的許多實用屬性不相容,例如能力路徑稽核、重新啟動時的持續性等。

替代方案:破壞

當做為優惠來源的動態元件遭到刪除時,除了刪除優惠之外,還有許多合理的行為。本節將討論這些替代方案。

禁止破壞來源

這項 RFC 的先前草案建議,如果元件是動態供應項目的來源,就禁止銷毀該元件。以這種方式「釘選」元件,直到這些優惠的目標遭到刪除為止。

從一開始,這似乎就相當脆弱,而且可能造成人體工學問題 (也就是說,「無法終止元件」錯誤可能非常難以處理)。不過,隨著 RFC-0101 獲得採用,情況變得難以處理,因為這項 RFC 導入了元件會自動毀損的情境。

刪除作業傳播

另一項提案是讓銷毀作業沿著提案傳播。也就是說,如果動態商品的來源遭到毀損,目標也會遭到毀損,依此類推,遞迴毀損。

這個選項似乎很可怕,而且與其他 CFv2 行為不一致。在許多情況下,功能無法路由傳送或無法使用,但即使依附元件非常依賴這些功能,也不會強制終止或毀損這些元件。元件可以觀察到依附元件無法使用,並視需要終止。

更新:移除許可清單

這項功能已證實可成功在動態元件中強制執行最低權限。

隨著 web_instance 元件遷移至新式元件架構,這項功能可能在 Chromium 程式碼庫中發揮效用。這個元件目前會使用舊版元件架構的功能啟動動態子項。這些子項的功能集可在執行階段有所不同,且啟用特定功能時,系統會在建立舊版元件期間,透過 additional_services 欄位為子項提供額外的通訊協定功能。動態供應項目可讓 web_instance 在執行階段決定哪些動態子項會收到額外功能,為這項行為提供明確且簡單的遷移路徑,以便遷移至現代元件架構。

因此,許可清單將移除,用戶端可使用這項功能,不必獲得元件架構團隊核准。

移除許可清單後,系統會進行下列變更:

  • 撰寫如何使用動態優惠的說明文件。
  • 從 CMC 移除 dynamic_offers 受限功能鍵。
  • 刪除 dynamic_offers 中的許可清單//tools/cmc/build/restricted_features