RFC-0028:處理權限

RFC-0028:帳號代碼權利
狀態已接受
區域
  • FIDL
說明

在 FIDL 中註解必要或排除的控制代碼權利。

作者
提交日期 (年-月-日)2019-04-01
審查日期 (年-月-日)2019-04-18

「The Right Stuff」

摘要

在 FIDL 中註解必要或排除的控制代碼權利,具體來說:

  1. 具備機制,可說明所有控制代碼類型 (例如 Protocolrequest<Protocol>handle) 的權利

  2. 在序列化時,強制執行權利篩選,也就是權利說明會決定遮罩,指出必須擁有的權利集。

  3. 在還原序列化時,強制執行權限驗證和提供的權限集。

提振精神

控制代碼權限是 Fuchsia 內用來降低權限的工具。在此 FTP 之前,FIDL 無法說明控制代碼權限。目前,有幾個地方對控制代碼權利設有重要限制或規定,因此這類說明會降級為方法註解。

理想的權限限制包括唯讀 IPC 或 VMO 控制代碼,以及不可執行的 VMO 控制代碼。

可寫入的 IPC 控制代碼即為理想的權限需求範例。

設計

權利限制

這項提案為 FIDL 新增一種限制:權限註解。這項功能可套用至 FIDL 資料結構和方法參數中的所有控制代碼類型:控制代碼、通訊協定和通訊協定要求。

權利限制「可以」在型別控制代碼宣告中指定: handle<*subtype*, *RC*>。因為權利只在特定控制代碼子類型的情境中才有意義,因此無法在一般控制代碼上指定權利。如果控點宣告未指定權限限制,系統會轉送權限,且權限不變 (現有行為不會變更)。

範例:

handle<vmo, zx.rights.READ | zx.rights.WRITE> 必須具備讀取和寫入權限,傳送給用戶端時會移除其他權限

handle<vmo> 未指定任何權利,轉送現有權利

每個權利限制都必須指定至少一項權利 (例如 handle<vmo, > 無效)。

伺服器和用戶端通訊協定端點 (myprotocolrequest<myprotocol>) 無法指定權限限制。這些端點一律會將權限 zx.TRANSFER | zx.WAIT | zx.INSPECT | zx.WRITE | zx.READ | zx.SIGNAL | zx.SIGNAL_PEER 和子類型設為管道。如需自訂權限 (例如用於不可移動的通訊協定),可以使用 handle<*channel*, *RRC, ORC*>。(這項功能可能會透過範本進一步改良,我們會在日後的 FTP 中討論)。

權利限制「必須」遵循「預設拒絕」政策。必須明確列出所有權利。

語法

控制代碼權限限制是位元型別的運算式,可透過位元運算子指定。在上述範例中,| 是位元 OR 運算子。這項語法適用於 FIDL 語言中其他位置的位元型別值。在 zx 程式庫中,會有包含所有權利的位元定義 zx.rights。

雖然重複的權利規格 zx.rights.[*right*] 相當冗長,但我們已提議在日後的 FTP 中縮短這項規格,因此不屬於本次 FTP 的範圍。

繫結

繫結「必須」回應控制代碼的接收和還原序列化,方法是毀損訊息並關閉管道 (使用墓誌銘 ZX_ERR_ACCESS_DENIED),因為這類控制代碼的必要權限不正確。

繫結「必須」回應控點的序列化,方法是序列化失敗、毀損訊息,並禁止傳送,因為這類控點的必要權限不正確。繫結也「必須」使用 ZX_ERR_BAD_STATE 關閉管道。

預設值

系統不會預設帳號代碼權限。原因如下:

  • 預設值的行為不明確,且可能因物件類型而異。 使用者無法清楚瞭解特定物件的預設權利。

  • 預設值會避免使用精細的控制代碼權限,因此在編寫 FIDL 定義時,很容易會忽略權限。

  • 如果存在預設值,對於許多物件類型而言,最適合的候選項目會是無權或最大權。如果預設值為最高權利,會限制這項 FTP 變更的效力,但如果預設值為無權利,效果會與沒有預設值相同。但這兩者都不太實用。

重複使用控制代碼聲明

如果沒有預設值,指定權限時可能會很冗長。 為改善這點,您可以使用別名功能 (即使用關鍵字),為整個控制代碼宣告命名。

using readable_vmo = handle<vmo, zx.READ>

另一種做法是允許權利限制的別名 (例如 iozx.READ | zx.WRITE 別名),但這會提供一層間接層,遮蓋權利,尤其是在廣泛使用權利的情況下。允許物件層級的別名,可將使用限制在類型相同的地點。

可參數化

我們想建立含有管道的泛型訊息,這些管道的權利限制可以參數化。

舉例來說,假設 fuchsia.mem.Buffer 包含 handle<vmo>。應該可以說 fuchsia.mem.Buffer:C,並將限制 C 傳送至限制 handle<vmo>

廣義型別別名是這方面的起點,而範本的導入將進一步滿足這項需求。雖然這不在本提案的範圍內,但相關工作必須考量這項需求。

導入策略

訊息接收作業應依賴 zx_channel_read_etc 系統呼叫,在呼叫點提供權利資訊。繫結會使用權利資訊驗證是否具備必要權利,並篩除必要權利以外的任何額外權利。

傳送訊息時應依據 zx_channel_write_etc,這會將傳送權限減少至一組指定權限,並驗證所有必要權限是否都存在,如果驗證失敗則會傳回 ACCESS_DENIED。收到這項回應後,繫結會負責關閉管道。為配合現有行為,這個系統呼叫會使用 ZX_HANDLE_OP_MOVE,這等同於呼叫 zx_handle_replace,然後呼叫 zx_channel_write。如果未指定任何權利,系統會使用 ZX_RIGHT_SAME_RIGHTS 取代權利。

我們正在準備實作文件,詳細說明實作方式。

人體工學

從長遠來看,這項功能可提升人體工學。權利文件和檢查作業會以標準方式在 FIDL 中進行,而不是臨時註解和檢查。

說明文件和範例

這項作業需要變更下列說明文件:

回溯相容性

ABI 相容性

權限變更不得破壞 ABI 相容性。

來源相容性

權限異動「可能」會導致來源相容性中斷。不過,破壞來源相容性是意料之外的情況,如果繫結作者選擇這條路,就應清楚記錄。

新增必要權限

訊息收件端可回溯相容,因此會額外取得必要權限,因為這只會增加能力。不過,在郵件寄件者端,新增必要權限是回溯不相容的變更,因為現在必須先具備權限才能傳送郵件。

移除必要權利

寄件者端可回溯相容,移除必要權限,但收件者端則無法回溯相容。收件者現在不會收到預期的權利。

新增選用權利

您可以回溯相容的方式新增選用權利。

移除選用權利

在傳送端,這項功能可回溯相容,移除選用權利,但在接收端則不相容。收件者現在不會收到先前可能收到的權利。

環境假設

這個模型部署作業可能會違反環境假設。舉例來說,用戶端可能會假設透過連線收到的所有 VMO 都是可對應的,即使伺服器無意提供這項保證。

您可以將這個狀態視為這項 FTP 的整體動機:移除這類普遍且隱含的合約。

效能

微基準測試顯示,zx_channel_write_etczx_channel_read_etc 的效能非常相似。如果是含有 1 個控制代碼的 64 位元組訊息,zx_channel_write/zx_channel_read 需要 962 奈秒,而 zx_channel_write_etc/zx_channel_read_etc 則需要 1000 奈秒。

讀取或寫入控制代碼時所需的控制代碼陣列,會從 256 個位元組 (ZX_CHANNEL_MAX_MSG_HANDLES * sizeof(zx_handle_t)) 增加到 1024 個位元組 (ZX_CHANNEL_MAX_MSG_HANDLES * sizeof(zx_handle_info_t))。同樣地,寫入控制代碼時堆疊分配的陣列會從 256 個位元組增加至 1280 個位元組 (ZX_CHANNEL_MAX_MSG_HANDLES * sizeof(zx_handle_disposition))

為了將堆疊配置保持在最多 256 個位元組,如果控點表格過大 (讀取作業超過 16 個控點,或寫入作業超過 12 個控點),我們需要堆積配置控點表格。為因應這項異動,我們將一併考量訊息大小和控制代碼表格的堆疊配置需求 (目前只考量訊息大小)。

安全性

這是為了提升安全性。有助於更準確地稽核我們的 API 介面。這項功能會將權限檢查移至繫結,與所有呼叫網站的相同檢查相比,這項檢查更適合審查。

舉例來說,權利完全用盡後,您就能輕鬆稽核所有轉移可執行 VMO 擁有權的位置。但現在要做到這一點並不容易。

測試

每個繫結實作項目都應進行單元測試。

推出這項功能時,也應確保修改後的 FIDL 通訊協定實作項目會測試新功能。

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

缺點:公開 API 會很冗長

從某種意義上來說,這項功能是「有雜訊」的。在系統的典型執行作業中,可能永遠不會採用缺少權限的路徑。但這些項目仍會佔用公用系統 API 的實際空間。

我們認為這項成本值得付出,因為可帶來清晰度和準確度,而且善用別名就能滿足大部分需求。

舉例來說,有兩類問題可以避免或減少:

  1. 因權利不相容而導致遠端中斷:故障可能發生在距離來源很遠的地方 (如果控制代碼再次轉移,甚至可能發生在其他程序的下游)。

  2. 未記錄的假設會導致相容性問題:部分用戶端/伺服器傳遞的控制代碼可能具有超出嚴格需求的權限,導致對等互連端假設這些權限存在,如果這些假設證明有誤,就會導致相容性問題。

我們瞭解詳列權限很煩人,但這等同於輸入能力資訊。

替代方案:權利的下限和上限

初始設計要求權限的上下限 (例如「沒有可執行權限」或「具有寫入權限」)。從安全性的角度來看,Fuchsia 應對所有功能 (和權利) 採用「預設拒絕」政策。

因此,如果某項能力 (或權利) 未在任何地方明確提及,就不應授予。元件資訊清單已採用這種做法,以進行沙箱化,理想情況下,FIDL API 也應如此。

我們可能還想明確表示「選用權利」,也就是可能提供或不提供的權利。

因此,就限制語法而言 (也就是使用者在編寫 FIDL API 時輸入的內容),我們正朝向列出權限,並將部分權限標示為選用。

請注意,從限制條件語意角度來看 (也就是需要在 JSON IR 中表示,並由繫結實作的內容),這項語法變更會繼續表示下限和上限檢查。

強制來源相容性

在 Fuchsia 中,權利通常以 uint32 表示,權利值隨時可能變更。因此,您可能會認為 FIDL 中的權利值變更,不應實質上導致產生的原始碼發生變更。不過,在某些情況下,可能需要打破來源相容性,例如在有特定權限 (本例中為 zx.rights.WRITE) 時產生特定方法 (例如 write())。因此,我們不會規定權限變更不得打破來源相容性。