RFC-0107:動態優惠 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 允許在執行階段在 CFv2 中建立優惠。 |
變更 | |
作者 | |
審查人員 | |
提交日期 (年/月) | 2021-05-24 |
審查日期 (年/月) | 2021-06-24 |
摘要
在元件架構 v2 (CFv2) 中,「父項元件」可以使用集合在執行階段將動態子項元件加入拓撲。不過,您無法在執行階段設定「已提供」給這類動態子項元件的功能組合。優惠會在父項元件的資訊清單中宣告,在父項元件開始執行時無法變更。
父項元件的資訊清單會統一處理指定集合中的所有動態子項;它甚至無法提及集合中的個別元件。這意味著某些限制:
- 您無法為個別動態子項提供能力。為集合提供能力,可讓您對該集合中的「所有」動態子項提供能力。
- 您無法為個別動態子項提供其他元件的能力。如果從集合提供某項能力,系統會建立匯總 FIDL 服務,以連線至該集合中的「任何」動態子項。
本文件提議「動態方案」,可在執行階段新增至元件拓撲。
相關人員
- 在執行階段建構動態拓撲的 CFv2 使用者。他們將以駕駛架構團隊表示。
- 元件架構區域擁有者:可以驗證設計是否合理,且不會與未來任何計畫相衝突。
- 安全性,負責確保這項功能不會損害系統安全性屬性。
提振精神
大部分的 CFv2 用途都涉及元件的靜態拓撲,以完成某些工作。這些元件之間的身分和關係一開始就知道,且能以硬式編碼的方式寫入元件資訊清單中。
在其他應用實例中,開發人員不知道執行的確切元件組合,但「可以」瞭解這些動態元件之間的關係。開發人員可以將所有動態元件分成一組,特定集合中的每個元件都會提供一組相同的功能。
然而,有些 CFv2 使用者想要在執行階段建構複雜的拓撲,為每個動態子項提供一組專屬功能,並在動態子項之間轉送功能。
用途:驅動程式即元件
在驅動程式架構的驅動程式式元件專案中,動態執行個體化的驅動程式庫元件會仰賴其他動態執行個體化驅動程式庫元件所提供的功能。我們會將某個驅動程式庫元件提供的功能呼叫另一個跨驅動程式功能。
CFv2 本身並不支援跨驅動程式庫功能。驅動器架構團隊在 driver_manager
本身中實作類似能力轉送功能的做法。這個解決方法有一些大致上的限制,並可能在跨驅動程式庫功能與「一般」功能之間產生令人困惑的差異:
- 元件會在傳入的命名空間中開啟路徑,藉此連線至「標準」功能,但會透過駕駛架構專屬的
exposed_dir
欄位連線至跨驅動程式庫功能。 - 指定
exposed_dir
後,接收元件即可存取其依附元件實作的「所有」通訊協定。driver_manager
不會讓接收器只能存取自己所需的通訊協定。驅動程式架構團隊可以修正此問題,但這麼做會導致進一步複製元件架構機制。 - 驅動程式元件需要在資訊清單的
use
區段中宣告其依附的「一般」功能,但不應以相同方式列出跨驅動程式庫功能。如果支援,元件管理服務就無法找到offer
來滿足use
。- 目前,元件管理服務大多會忽略這些多餘的
use
,但可能會在短期內造成混淆,而多餘的use
可能長期是一個錯誤。
- 目前,元件管理服務大多會忽略這些多餘的
驅動程式作者閱讀的「一般」功能不應和跨驅動程式庫程式功能不同,因此應盡快移除區別。等待的時間越長,當模型變更時,需要遷移的驅動程式就越多。
設計
本提案擴充了 fuchsia.sys2.Realm/CreateChild
API,以接受 OfferDecl
清單,其中說明將為新建的子項提供的其他功能,且除了通常系統提供的功能外。我們將這種方式稱為 OfferDecl
做為「動態優惠」。以一般方式指定的 OfferDecl
(在元件資訊清單中列出) 稱為「靜態優惠」。
任何類型的優惠 (例如通訊協定、目錄等) 都可以做為動態優惠使用。
動態優惠一律會指定新建立的子元件。因此,指定元件的動態優惠組合會在元件建立時得知,之後無法變更。(指出是否必須實際指定 OfferDecl
的 target
欄位,Google 會在 API 審查中加以判定)。
動態優惠適用的任何來源也都對動態優惠有效。此外,與靜態優惠不同的是,動態優惠可以使用「同層級」動態子項元件 (即與目標具有相同父項的元件) 做為來源。如果動態優惠具有動態子項做為來源,則目標必須與來源必須屬於同一個集合。
建立子項元件後,動態優惠的行為應與靜態優惠完全相同,包括元件關閉順序等事項。
破壞
如果有動態優惠的來源或目標遭到刪除,動態優惠就會遭到刪除。刪除優惠後,系統的行為會完全相同。
如果可以,動態優惠的使用者應優先刪除來源,然後再刪除來源。如果優惠是即將刪除的目標,則將優惠從拓撲中移除的程序會很複雜 (如果優惠位於森林中,且沒有元件能夠聽到這項訊息...)。但是,有時無法提供協助,而且來源會在目標之前遭到刪除。要注意的是,使用單一執行集合 (在 RFC-0101 中引入) 時,動態元件會在終止後立即刪除,而且隨時可能發生。
即使這是要刪除的來源,處理程序也十分直觀:
- 元件管理員會關閉來源元件。這種做法可防止目標開啟任何對來源的新連線,並指示執行元件停止來源元件 (如果來源元件正在執行)。
- 來源元件停止時,來源與目標之間的任何管道都會關閉。
- 來源元件和動態優惠將會同時從拓撲中移除。
從目標的角度來看,與能力對應的管道關閉,以及任何嘗試重新取得能力操作均會永久失敗,就像沒有能力一開始就轉送一樣。
這項 RFC 並未提供重新建立這類優惠的機制。
依附元件週期預防
CFv2 規定元件及其之間的強大優惠必須形成有向非循環圖,以便元件能夠按照依附元件順序妥善關閉。以靜態優惠來說,我們可以查看元件資訊清單,確保沒有依附元件週期。
以動態優惠來說,下列預防措施足以確保非循環依附元件圖表:
- 動態元件建立順序具有嚴格的總順序。也就是不會同時新增兩個動態元件至拓撲。
- 動態優惠一律會與目標元件同時建立。
- 所有優惠 (包括靜態和動態的優惠) 均無法變更。
- 所有優惠 (包括靜態和動態) 都必須具備有效的來源和目標。這項屬性會由
CreateChild
在動態優惠建立過程中檢查,當來源或目標遭到刪除時,優惠也會遭到刪除。
綜上所述,這意味著動態優惠的來源一律比其目標舊。如果來源較年輕,就代表該項目在建立目標時不存在,因此優惠在建立時會具有無效的來源。由於「建立順序」採用嚴格的總順序,因此不可能使用依附元件週期。
處理無效路徑
在本文撰寫期間,元件管理服務不會主動拒絕轉送設定無效的元件資訊清單。也就是說,如果某項能力提供的來源未公開,或者某個元件未收到該元件所用能力的優惠,就不會在元件建立時引發錯誤。只有在元件嘗試開啟無效轉送能力時,才會引發錯誤。
基於「動態優惠」的精神,我們在此實作相同的行為。元件可能會針對來源未公開的能力建立動態優惠。同樣地,父項元件也可以建立動態子項元件,但未針對該元件使用的每個能力提供優惠。
日後如果元件管理服務有所變更以提早傳回錯誤,我們也會變更 CreateChild
的合約,以便傳回錯誤。
實作
面向的使用者介麵包含:
- 與
CreateChild
API 回溯相容的變更,以便接受將動態優惠清單做為引數。 - 個別集合的選擇啟用設定,允許動態優惠以該集合中的元件為目標。(請參閱安全性考量中的討論)。
- 可能選擇啟用的父項元件的許可清單。(注意:請參閱更新:將許可清單移除)
(1) 的實作會完全位於元件管理服務本機。實作 (2) 和 (3) 可能會變更剖析 CML 檔案的工具。但無論如何,都不需要進行跨團隊協調。
效能
這項變更應該不會影響呼叫 CreateChild
和 DestroyChild
以外的系統效能,這些作業是罕見且不重要的作業。即使是這些作業,效能也不會受到影響。
人體工學
優惠刪除行為是全新的,如果元件的依附元件突然消失,可能會對這些元件的作者造成人體工學難題。
從目標元件的角度來看,判斷優惠一經刪除,要進行什麼並不容易,只能看到管道關閉而已。目標元件無法立即判斷來源元件是否已刻意刪除、停止或關閉管道。如要判斷來源是否已刪除,目標必須嘗試重新連線,並等待元件管理服務的回應來指出轉送永久失敗。
安全性考量
此設計本身會破壞 CFv2 的重要安全目標:應宣告所有能力路徑 (或可能的能力路徑),以便稽核。如要在測試之外使用動態優惠,必須確保除了元件資訊清單以外,其他機制能夠透過其他機制稽核潛在能力路徑。
透過這項功能,驅動程式架構會接受責任,確保可稽核潛在能力路徑的空間。目前這些規則會以多個位置編碼,包括去中心化繫結規則、電路板驅動程式的原始碼、ACPI 等等。這使得稽核過程充滿挑戰。這個缺口不是全新項目,必須由驅動程式架構解決,但做法不在這個 RFC 的範圍內。
系統會在 CollectionDecl
中新增選擇啟用設定,現在該設定可讓父項元件將動態優惠傳送至該集合中建立的元件。這會讓 CML 審查人員清楚瞭解動態優惠目前正在使用中,且需要諮詢元件資訊清單以外的來源,才能瞭解可能的能力路徑範圍。
此外,選擇加入功能會由元件架構團隊加入許可清單,方便他們確保所有使用情況適當。(注意:請參閱「更新:移除許可清單」)
未來的工作
如果發現更多動態優惠用途,我們可能會在元件資訊清單結構定義中加入「優惠上限」。優惠上限可用來限制可在執行階段建立的動態優惠類型。
資訊清單應包含下列陳述式:
- 「通訊協定
fuchsia.example.Foo
可從元件A
動態提供給B
集合中的任何元件」或 - 「您可以在
C
集合中的任兩個元件之間動態提供任何目錄能力」。
在初始驅動程式架構用途中,我們認為概略收集層級選擇的選擇已足夠。將其他用戶端加入許可清單前,您必須重新評估此情況。
隱私權注意事項
這個提案不會向系統無法存取的資料公開系統的任何部分,因此不會對隱私權產生任何影響。
測試
新增單元和整合測試的涵蓋範圍,類似於任何其他元件架構功能。將由駕駛架構的整合測試間接提供。
這項功能應該對於 ComponentFramework API 的可測試性並不會有幫助或影響。如要使用集合和 Realm
通訊協定,就必須在整合測試設定中與真正的元件管理服務執行個體搭配使用,且同樣會如此。
說明文件
由於動態優惠會加入許可清單,且最初只有單一用戶端使用,因此高階元件架構說明文件不應更新來提及這項功能的存在。CreateChild
、DestroyChild
和 CollectionDecl
變更的說明文件應已足夠。
將其他用戶端加入許可清單前,您必須重新評估這項標準。
缺點、替代方案和未知
這項設計的主要缺點是,稽核能力路徑會變得更加複雜,因為並非所有可能的能力路徑都會顯示在元件資訊清單中。不過,這是驅動程式架構的內建函式:驅動程式庫元件的拓撲本質上是動態的,因為可以即時從機器新增及移除裝置。靜態優惠的內容明確不足,因此故事「必須」變得更複雜。動態優惠會盡可能建立靜態優惠的行為鏡像,嘗試將額外的複雜程度保持在最低限度。
替代功能:功能權杖
先前提出功能權杖是為瞭解決相關問題。該提案可視為這個 RFC 的通用化,在運作範圍之間提供動態優惠。來源元件的父項「挖掘」能力權杖,此權杖會傳遞給另一個父項元件 (可能透過中繼元件鏈結)。接收元件可將這個權杖傳遞至 CreateChild
,做為授權機制,表示兩個父項都同意優惠。
建立後,這項動態優惠的行為應與靜態優惠類似,不過這些動態優惠可能會跨越運作範圍的主要例外狀況。靜態優惠 (在主要提案中,也可以使用動態優惠) 一律會只針對單一父項元件。
跨領域產品帶來的影響不甚明確,且我們不認為有必要這麼做,因此拒絕了這個選項。
替代做法:提供「即時能力提供者」
在主要提案中,動態優惠是原始資料。優惠代表元件管理服務應如何轉送要求以提供能力,但無法自行提供能力存取權的操作說明。
我們可以改為傳遞「功能提供者」,後者可直接取得功能。CreateChild
隨即會接受已命名能力提供者的向量。當動態子元件嘗試開啟動態提供的能力時,系統會將 Open
要求轉送至能力供應程式。
父項元件可透過下列方式取得這類能力提供者:
- 自行實作能力供應器
- 呼叫
Realm
API,取得父項或子項公開功能的能力供應器,或 - 透過管道接收來自其他元件的能力供應者。
這麼做可解鎖與能力權杖相同的用途,但父項能直接為功能提供者提供功能提供者的額外好處 (或可帶來負面影響):只要在記憶體中啟動伺服器,並將能力供應器傳遞至 CreateChild
即可。
但是,能力提供者與 CFv2 轉送架構的許多重要屬性不相容:能力路徑的可稽核性、重新啟動之間的持續性等。
替代方案:刪除
做為優惠來源的動態元件刪除時,除了刪除優惠以外,還有許多合理行為。本節將說明這些替代方案。
出價來源刪除
如果元件是動態優惠的來源,則這份 RFC 稍早提議將元件的出價刪除。元件會以這種方式「固定」,直到相關優惠的目標刪除為止。
即使一開始,這種似乎很脆弱,也呈現了潛在的問題,也就是「元件無法刪除」錯誤非常難以處理。不過,接受 RFC-0101 後就無法正常運作,因為這種情況提出了會自動刪除元件的情況。
破壞傳播
另一個提案需要刪除才能連同優惠一併傳播。也就是說,如果動態優惠的來源遭到刪除,目標也會以遞迴方式刪除。
這個選項似乎令人驚慌,與其他 CFv2 行為不一致。在許多情況下,功能無法路由或無法使用,且這些情況都不會導致相依元件的強制終止或刪除,即使依附元件十分強大。元件可以觀察其依附元件無法使用並退出 (也可以選擇退出)。
更新:移除許可清單
事實證明,這項功能已成功在動態元件中強制執行最低權限。
這項功能在 Chromium 程式碼集內可能包含公用程式,以便將 web_instance
元件遷移至現代化元件架構。目前這個元件會使用舊版元件架構的功能啟動動態子項。這些子項的功能組合可在執行階段變更,當啟用特定功能時,子項會在建立舊版元件時,透過 additional_services
欄位提供額外的通訊協定功能。動態優惠會透過允許 web_instance
決定在執行階段,讓動態子項接受額外功能,進而提供簡單易懂的遷移路徑,讓您輕鬆遷移至現代元件架構。
因此,系統會移除許可清單,因此用戶端不必收到元件架構團隊的核准,就能使用這項功能。
為了讓許可清單移除,會發生下列變化:
- 撰寫說明文件,瞭解如何使用動態優惠。
- 從 CMC 中移除「
dynamic_offers
」受限的功能金鑰。 - 刪除
//tools/cmc/build/restricted_features
中的dynamic_offers
許可清單。