本頁面會逐步說明 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
納入處理序中,以指定 FIDL 類型:MAP
、READ
和WRITE
的權利。這會告知核心在轉移h1
時應提供什麼權利。繫結並不瞭解h1
實際具有哪些權限。(他們不知道 VM 也會參照 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
Syscall 或類似系統。
核心
- 確認寄件者程序的帳號代碼資料表中有
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
Syscall 或類似系統。 從傳回的帳號代碼資訊中解除
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
服務。
- 使用