RFC-0107:動態優惠

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

允許在 CFv2 執行階段建立優惠。

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

摘要

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

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

  1. 無法將能力提供給個別動態子項。如果將能力提供給集合,則該集合中的「所有」動態子項都會具備該能力。
  2. 您無法將個別動態子項的能力提供給其他元件。從集合提供能力會建立匯總 FIDL 服務,允許連線至該集合中的「任何」動態子項。

本文件提出「動態供應項目」,可在執行階段新增至元件拓撲。

相關人員

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

提振精神

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

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

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

用途:驅動程式做為元件

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

CFv2 原生不支援驅動程式庫間功能。Driver Framework 團隊已在 driver_manager 中實作類似能力轉送的功能,藉此解決這個問題。這項解決方法有一些相當粗糙的邊緣,並會暴露驅動程式庫間功能與「正常」功能之間令人困惑的差異:

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

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

設計

這項提案擴充了 fuchsia.sys2.Realm/CreateChild API,可接受 OfferDecl 清單,說明新建立的子項除了通常提供的功能外,還會提供哪些額外功能。我們將以這種方式指定的 OfferDecl 稱為「動態方案」。以一般方式指定的 OfferDecl (即列在元件資訊清單中) 則稱為「靜態方案」。

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

動態優惠一律會指定新建立的子元件。因此,在建立元件時,系統就會知道指定元件的動態優惠組合,且之後無法變更。(是否必須實際指定 OfferDecl 的 target 欄位,將在 API 審查中決定)。

任何適用於靜態優惠的來源,也適用於動態優惠。此外,與靜態優惠不同,動態優惠可以使用「同層」動態子項元件 (即與目標具有相同父項的元件) 做為來源。如果動態優惠以動態子項做為來源,則目標不一定要與來源位於同一個集合中。

建立子元件後,動態方案的行為應與靜態方案完全相同,包括元件關閉順序等考量。

破壞

當動態優惠的來源或目標遭到刪除時,動態優惠也會一併刪除。優惠銷毀後,系統會完全按照從未存在過的方式運作。

如果可能,動態供應項目的使用者應優先刪除目標,再刪除來源。如果遭到刪除的是目標,從拓撲中移除供應項目的程序就很簡單 (如果供應項目落在森林中,且周圍沒有元件可以聽到...)。不過,有時無法避免這種情況,來源會在目標之前遭到刪除。值得注意的是,使用單次執行集合 (RFC-0101 中介紹) 時,動態元件會在終止時立即刪除,這可能隨時發生。

即使是來源遭到刪除,程序也很簡單:

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

從目標的角度來看,與能力對應的管道會關閉,任何重新取得能力的嘗試都會永久失敗,就像能力一開始未轉送一樣。

這項 RFC 未提供重新建立這類提議的機制。

避免依附元件循環

CFv2 要求元件和元件之間的強烈供應項目形成有向無環圖,以便元件能依依附元件順序正常關閉。如果是靜態供應項目,我們可以查看元件資訊清單,確保沒有依附元件週期。

對於動態優惠,下列規則足以確保非循環依附元件圖:

  1. 動態元件建立順序是嚴格的全序關係。換句話說,不會有兩個動態元件同時加入拓撲。
  2. 動態優惠一律會與目標元件同時建立。
  3. 所有優惠 (靜態和動態) 均不可變更。
  4. 所有優惠 (靜態和動態) 都必須有有效的來源和目標。CreateChild 會在動態建立優惠時檢查這項屬性,且只要來源或目標遭到刪除,優惠也會一併刪除。

總而言之,動態優惠的來源一律會比目標舊。如果來源較新,表示目標建立時來源不存在,因此優惠在建立時會含有無效來源。由於「建立順序」是嚴格的全序關係,因此不可能出現依附元件循環。

處理無效路徑

截至本文撰寫時,元件管理服務不會主動拒絕轉送設定無效的元件資訊清單。也就是說,如果能力是由未公開該功能的來源提供,或者元件未收到其所用能力的提供,則在元件建立時不會引發錯誤。只有在元件嘗試開啟無效轉送的能力時,系統才會顯示錯誤。

本著「動態優惠應與靜態優惠行為相同」的精神,我們將在此實作相同的行為。元件可能會為來源未公開的能力建立動態方案。同樣地,父項元件可以建立動態子項元件,而不必為其使用的每項能力提供。

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

實作

這項異動的面向使用者介面包括:

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

(1) 的實作將完全由元件管理服務在本機執行。實作 (2) 和 (3) 可能需要變更剖析 CML 檔案的工具。無論如何,都不需要跨團隊協調。

效能

這項異動不會影響系統效能,但對 CreateChild 和 DestroyChild 的呼叫除外,這些呼叫很少見,且不會影響效能。即使是這些作業,預期也不會對效能造成負面影響。

人體工學

優惠銷毀行為是新功能,可能會為依附元件突然消失的元件作者帶來人體工學挑戰。

從目標元件的角度來看,要判斷供應項目刪除後發生的情況並不簡單:它只會看到管道關閉。目標元件無法立即判斷來源元件是否遭到刪除、停止或刻意關閉管道。為判斷來源是否確實遭到刪除,目標必須嘗試重新連線,並等待元件管理服務傳回回應,指出永久無法轉送。

安全性考量

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

使用這項功能,即代表 Driver Framework 負責確保潛在能力轉送的空間可供稽核。目前,規則會在多個位置編碼:分散式繫結規則、主機板驅動程式的原始碼、ACPI 等。這會增加稽核難度。這個落差並非新問題,需要由 Driver Framework 解決,但如何解決則不在本 RFC 的討論範圍內。

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

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

未來工作

如果我們發現動態優惠有更多用途,可能會在元件資訊清單結構定義中,加入優惠上限。優惠上限可用來限制執行階段可建立的動態優惠類型。

資訊清單會包含以下陳述式:

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

對於初始 Driver Framework 用途,我們認為較粗略的集合層級選擇加入就足夠。將其他用戶端加入許可清單前,務必重新評估這個立場。

隱私權注意事項

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

測試

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

這項功能不應影響 Component Framework API 的可測試性。使用集合和 Realm 通訊協定時,就必須在整合測試設定中使用實際的元件管理服務執行個體,這點不會改變。

說明文件

由於動態優惠會加入許可清單,且一開始僅供單一用戶端使用,因此高階元件架構概念說明文件不應更新,以提及這項功能的存在。CreateChild、DestroyChild 和 CollectionDecl 的變更說明文件應足以說明。

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

缺點、替代方案和未知因素

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

替代方案:功能權杖

先前曾有人提議使用功能權杖解決相關問題。該提案可視為這項 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 受限功能金鑰。
  • 刪除 //tools/cmc/build/restricted_features 中的 dynamic_offers 許可清單。