RFC-0013:複製 VMO 對應

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

系統呼叫,可從對應項目建立 VMO 的 CoW 副本,不需要控點。

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

摘要

目前只有在擁有 VMO 控制代碼的情況下,才能建立 VMO 的 CoW 副本。這不足以用於 Zygote 使用情境,因為這類情境需要 CoW 複製整個位址空間,包括所有 VMO 控制代碼已關閉的對應。這項 RFC 提議採用新的系統呼叫,以解決這個缺口。

動機和問題陳述

Linux 上的 Chromium 會從 Zygote 程序分叉,藉此產生算繪器,大幅節省記憶體和 CPU 資源。我們希望在 Fuchsia 上實現這些節省。

為此,我們需要實作「位址空間複製」作業,

  • 程序根 VMAR
  • 某些控點會參照位址空間中對應的 VMO

以上指令會傳回:

  • 新程序,其位址空間會填入輸入程序中對應 VMO 的副本
  • 對於輸入程序中參照 VMO 的每個控制代碼,新程序中參照該 VMO 對應複製項的新控制代碼

加入這個系統呼叫後,我們就能在使用者空間中輕鬆實作這項功能。這項作業的原理是使用 ZX_INFO_PROCESS_MAPS 取得位址空間配置,並使用 zx_vmar_create_vmo_child 建立每個對應的副本,但有控制代碼的 VMO 除外,這些 VMO 會使用 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)

Creates a CoW clone of the pages mapped in the range addr to addr+size in the VMAR referenced by handle. 範圍必須是單一 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_vmo_create_child,藉此實作 zx_vmar_create_vmo_child 的使用者空間。但一般來說,Zircon API 只允許鑄造新建立物件的控制代碼,以便更容易分析介面。這個系統呼叫必須憑空建立控制代碼。

有許多技巧可用於避免關閉任何 VMO 控制代碼,例如修改所有建立及對應 VMO 的程式碼,避免關閉這些控制代碼,或是攔截 zx_handle_close。不過,這不足以實作位址空間複製,因為載入器服務會在程序開始執行前,將部分 VMO 對應至程序,而這無法協助您取得這些 VMO 的控制代碼。我們可以修改載入器服務,將必要的控制代碼傳遞至程序,但這比新增這個系統呼叫更費工。

既有技術和參考資料

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