本頁面將逐步說明 FIDL 如何將 Zircon 控制代碼從一個程序轉移到另一個程序。特別是著重於「處理權利」的各種意義,以及如何驗證處理權利。
情境
假設簡單的用戶端和伺服器透過下列通訊協定進行通訊:
protocol LifeOfAHandle {
Method(resource struct {
h zx.Handle:<VMO, zx.Rights.MAP | zx.Rights.READ | zx.Rights.WRITE>;
}) -> ();
};
假設我們從控制碼權限中移除 zx.Rights.WRITE,但只重新編譯伺服器,而非用戶端。用戶端建立 VMO 並傳遞至 Method 時會發生什麼情況?
圖表
在此情境中,用戶端會做為「傳送者」,伺服器則會做為「接收者」。我們在下文中使用這些字詞,是因為這對轉移帳號代碼來說至關重要。如果方法傳回控制代碼,則適用相同的步驟,但角色會反轉。
如需圖表的詳細說明,請參閱下文。
說明
使用者代碼 (寄件者)
- 假設傳送者使用
zx_vmo_create系統呼叫取得 VMO。傳回的控制代碼h1具有 VMO 的預設權限:DUPLICATE、TRANSFER、READ、WRITE、MAP、GET_PROPERTY和SET_PROPERTY。 - 呼叫
Method,並將h1傳遞至該函式。
- 假設傳送者使用
FIDL 繫結 (傳送端)
將
h1包裝在 handle disposition 中,指定 FIDL 型別的權限:MAP、READ和WRITE。這會告知核心在轉移h1時要提供哪些權利。繫結不知道h1實際擁有哪些權利。(他們也不確定是否參照 VMO,但與權限不同的是,這通常會以靜態型別系統表示,因此很難不小心傳遞錯誤的控制代碼型別)。zx_handle_disposition{ .operation = ZX_HANDLE_OP_MOVE, .handle = h1, .type = ZX_OBJ_TYPE_VMO, .rights = ZX_RIGHT_MAP | ZX_RIGHT_READ | ZX_RIGHT_WRITE, }叫用
zx_channel_write_etc系統呼叫 (或類似項目)。
核心
- 確認傳送端程序控點資料表中存在
h1。 - 確認
h1參照 VMO。 - 確認
h1至少擁有MAP、READ和WRITE權利。 - 將權利限制為僅包含
MAP、READ和WRITE,移除DUPLICATE、TRANSFER、GET_PROPERTY和SET_PROPERTY權利。我們將這個受限控制代碼稱為h2。這相當於叫用zx_handle_replace系統呼叫。 - 使用
h2而非h1將訊息加入佇列。
- 確認傳送端程序控點資料表中存在
FIDL 繫結 (接收器)
- 叫用
zx_channel_read_etc系統呼叫 (或類似項目)。 從傳回的控制代碼資訊中解除包裝
h2。與控制代碼處置不同,控制代碼資訊會儲存核心回報的控制代碼實際類型和權利。zx_handle_info{ .handle = h2, .type = ZX_OBJ_TYPE_VMO, .rights = ZX_RIGHT_MAP | ZX_RIGHT_READ | ZX_RIGHT_WRITE, }從 FIDL 類型取得預期類型和權利:
MAP和READ。確認
h2具有 (至少) 這些權利。由於
h2具有非預期的權利WRITE,請叫用zx_handle_replace系統呼叫,取得只具有MAP和READ權利的新控制代碼h3。
- 叫用
使用者代碼 (接收者)
- 使用
h引數 (即h3) 服務Method。
- 使用