RFC-0013:複製 VMO 對應

RFC-0013:複製 VMO 對應
狀態已接受
區域
  • 核心
說明

系統呼叫,可從對應建立 VMO 的 CoW 複本,而不需要對應的句柄。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2020-10-26
審查日期 (年-月-日)2020-12-09

摘要

目前只有在您擁有 VMO 的句柄時,才能建立 CoW 的複本。這對於 zygote 用途來說並不足夠,因為 CoW 需要複製整個位址空間,包括已關閉所有 VMO 句柄的對應項目。本 RFC 提出了新的系統呼叫,以解決這個差距。

動機和問題陳述

Linux 上的 Chromium 會從 zygote 程序分支轉譯器,藉此產生轉譯器,進而大幅節省記憶體和 CPU 用量。我們希望在 Fuchsia 上實現這些節省。

為此,我們需要實作「位址空間複製」作業的某種方式,在提供以下資訊時:

  • 程序根 VMAR
  • 部分參照在位址空間中對應的 VMOs 的句柄

會傳回:

  • 新的程序,其位址空間由輸入程序中對應的 VMOs 複本填入
  • 針對輸入程序中參照 VMO 的每個句柄,新程序中參照該 VMO 對應複本的新句柄

只要新增這個系統呼叫,我們就能輕鬆在使用者空間中實作這項功能。這項作業會透過 ZX_INFO_PROCESS_MAPS 取得位址空間版面配置,並使用 zx_vmar_create_vmo_child 建立每個對應項目的複本,但會排除任何有句柄的 VMOs,因為這些會透過 zx_vmo_create_child 處理。

設計

zx_vmar_create_vmo_child

zx_status_t zx_vmar_create_vmo_child(zx_handle_t handle,
                                     uint32_t options,
                                     zx_vaddr_t addr,
                                     size_t size,
                                     zx_handle_t* out)

handle 參照的 VMAR 中,在 addraddr+size 範圍內對應的頁面建立 CoW 複本。範圍必須是單一 VMO 對應項目的子範圍,也就是說,範圍不得跨越兩個對應項目,也不能包含任何未對應的頁面。結果是新的 VMO,是範圍中對應的 VMO 的子項。

允許的選項為 ZX_VMO_CHILD_SNAPSHOTZX_VMO_CHILD_SNAPSHOT_AT_LEAST_ON_WRITEZX_VMO_CHILD_NO_WRITE。解讀方式與 zx_vmo_create_child 相同。(ZX_VMO_CHILD_SLICE 目前不允許使用,因為安全性問題:必須特別小心,確保修改父項 VMO 的功能不會破壞任何安全性界線)。

如果符合下列情況,就會傳回 ZX_ERR_INVALID_ARGS

  • 範圍 addraddr+size 並非單一 VMO 對應項目的子範圍
  • addrsize 未對齊頁面

如果符合下列情況,就會傳回 ZX_ERR_ACCESS_DENIED

  • 對應是使用新的標記 ZX_VM_CANNOT_CREATE_VMO_CHILD 完成,或是 vmar 選項包含此標記
  • handle 沒有 ZX_RIGHT_INSPECT

如果 handle 不是有效的句柄,則會傳回 ZX_ERR_BAD_HANDLE;如果 handle 不是 VMAR,則會傳回 ZX_ERR_WRONG_TYPE;如果 VMAR 已遭到銷毀,則會傳回 ZX_ERR_BAD_STATE。如果符合說明中的情況,也可以傳回 zx_vmo_create_child 傳回的任何錯誤。

傳回的 VMO 句柄將包含 ZX_DEFAULT_VMO_RIGHTS,並且會進行以下變更:

  • 如果指定 ZX_VMO_CHILD_NO_WRITE,系統就會移除 ZX_RIGHT_WRITE
  • 如果對應項目可執行,且未指定 ZX_VMO_CHILD_NO_WRITE,系統會新增 ZX_RIGHT_EXECUTE。也就是說,您可以建立可執行對應項目的可執行複本,但必須是唯讀。

ZX_VM_CANNOT_CREATE_VMO_CHILD

ZX_VM_CANNOT_CREATE_VMO_CHILD 是新的 zx_vm_options_t 標記,可用於指定 VMO 對應或 VMAR。這可讓對應 VMO 或建立 VMAR 的程式碼禁止在這些項目上使用 zx_vmar_create_vmo_child

實作

新增系統呼叫並非複雜的變更,可在一個 CL 中完成。複製演算法的實作方式不在本 RFC 的討論範圍內。

成效

由於此系統呼叫只能用於 zygote 實作內容,因此不值得單獨對其進行基準測試。我們應該評估 zygote 實作項目的整體效能。

安全性考量

目前無法使用 VMAR 參照值 (而非句柄) 建立 VMO 子項,但這項 RFC 可讓您這麼做。這有點像是憑空授予新能力。

在這種情況下,由於最終結果與先前建立新 VMO 並複製資料 (但使用較少記憶體) 相同,因此風險似乎不高。如果需要禁止這項功能,本 RFC 建議可使用的 zx_vm_options_t 標記 (ZX_VM_CANNOT_CREATE_VMO_CHILD)。

測試

系統會對系統呼叫進行單元測試。針對未來實作位址空間複製功能的測試,也會做為系統呼叫的整合測試。

說明文件

這份 RFC 是 zx_vmar_create_vmo_child 說明文件的起點。

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

還有哪些策略可以解決同樣的問題?

我們可以新增系統呼叫,執行整個位址空間複製作業。無論是介面還是實作方式,這都會是相當複雜的系統呼叫。將複雜性推送至使用者空間會是較好的做法。

我們可以新增系統呼叫,允許從對應中鑄造 VMO 句柄。這可讓您實作 zx_vmar_create_vmo_child 的使用者空間,方法是先從對應建立句柄,然後呼叫 zx_vmo_create_child。不過,Zircon API 通常只允許為新建立的物件鑄造控制代碼,以便讓介面更容易推理。這個系統呼叫必須從空白中建立句柄。

您可以使用各種技巧來避免關閉任何 VMO 句柄,例如修改所有建立及對應 VMOs 的程式碼,以免關閉這些 VMO,或是攔截 zx_handle_close。不過,這項做法無法實現位址空間複製功能,因為載入器服務會在程序開始執行前將部分 VMOs 對應至該程序,這無法協助您取得這些程序的句柄。我們可以修改載入器服務,將必要的句柄傳遞至程序,但這比新增此系統呼叫更費工。

既有技術與參考資料

https://chromium.googlesource.com/chromium/src/+/master/docs/linux/zygote.md http://neugierig.org/software/chromium/notes/2011/08/zygote.html