FIDL 中帳號代碼的生命週期

本頁將逐步說明 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」?

圖表

在這種情況下,用戶端會以「寄件者」的身分運作,而伺服器的狀態為 接收器。我們使用以下字詞,是因為這會影響 轉移帳號代碼用途如果方法傳回控制代碼,則 步驟反向操作

如需圖表的詳細說明,請參閱下文

透過 FIDL 傳送帳號代碼的圖表

說明

  1. 使用者代碼 (傳送者)

    • 假設傳送方使用 zx_vmo_create 系統呼叫取得 VMO。 傳回的帳號代碼 h1 對 VMO 有預設權限:DUPLICATETRANSFERREADWRITEMAPGET_PROPERTYSET_PROPERTY
    • 呼叫 Method,並向其傳遞 h1
  2. FIDL 繫結 (傳送者)

    • h1 納入指定 FIDL 權利的帳號代碼 類型:MAPREADWRITE。這會讓核心瞭解 轉移 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 syscall (或類似模式)。

  3. 核心

    • 確保傳送方程序的控制代碼中含有 h1
    • 確保 h1 參照 VMO。
    • 確認h1 (至少) 擁有MAPREADWRITE的權利。
    • 將權限限制為只包含 MAPREADWRITE,並移除 權利 DUPLICATETRANSFERGET_PROPERTYSET_PROPERTY。 我們稱這個受限帳號代碼為 h2。這相當於 叫用 zx_handle_replace syscall。
    • 使用 h2 而非 h1 將訊息排入佇列。
  4. 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 類型中的預期類型和權利:MAPREAD

    • 確認h2具備這些權利 (至少)

    • 由於 h2 含有非預期的正確 WRITE,因此請叫用 zx_handle_replace 進行 syscall 以取得新控制代碼 h3, 權利 MAPREAD

  5. 使用者代碼 (接收端)

    • 使用 h 引數的 Method 服務,即 h3