變數指南

簡介

如「總覽」頁面所述,主機程式碼會對沙箱程式庫發出 RPC 呼叫。沙箱化會導致程序之間的記憶體分離,因此主機程式碼無法直接存取沙箱程式庫中的記憶體。

為確保主機程式碼可以存取遠端程序中的變數和記憶體區塊,並簡化主要邏輯程式碼的實作方式,SAPI 提供了一整套 C++ 類別。不過,在許多情況下,您也可以使用原生 C 型別。

將指標傳遞至簡單型別和記憶體區塊 (結構、陣列) 時,就需要使用特殊型別 (SAPI 型別)。

舉例來說,呼叫採用指標的函式時,指標必須轉換為 Sandboxed Library 記憶體中的對應指標。以下程式碼片段會以視覺化方式呈現這個情境。系統會建立 ::sapi::v::Array<int> 物件,而非三個整數的陣列,然後將該物件傳遞至 Sandboxed Library 的 API 呼叫:

int arr[3] = {1, 2, 3};
sapi::v::Array<int> sarr(arr, ABSL_ARRAYSIZE(arr));

如要全面瞭解所有可用的 SAPI 類型,請查看 SAPI 專案原始碼中的 var_*.h 標頭檔案。這些標頭檔案提供代表各種類型資料的類別和範本,例如:

  • ::sapi::v::UChar 代表未簽署的知名字元
  • ::sapi::v::Array<int> 代表整數陣列

SAPI 類型

本節將介紹主機程式碼中常見的三種 SAPI 類型。

SAPI 指標

如果要進行沙箱化的函式需要傳遞指標,則應從下列其中一個 PtrXXX() 方法取得指標。這些方法是由 SAPI 變數類別實作。

指標類型
::PtrNone() 傳遞至沙箱 API 函式時,不會在主機程式碼程序和沙箱程式庫程序之間同步處理基礎記憶體。
::PtrBefore() 在沙箱化 API 函式呼叫發生「之前」,同步處理所指向物件的記憶體。 也就是說,在啟動呼叫前,所指變數的本機記憶體會轉移至沙箱化程式庫程序。
::PtrAfter() 在沙箱化 API 函式呼叫發生「後」,同步處理所指向物件的記憶體。 也就是說,在呼叫完成,所指變數的遠端記憶體會轉移至主機程式碼程序記憶體。
::PtrBoth() 結合 ::PtrBefore()::PtrAfter() 的功能。

如要參閱 SAPI 指標的說明文件,請按這裡

SAPI 結構體

範本 ::sapi::v::Struct 記錄在 var_struct.h 中。這個範本提供可用於包裝現有結構的建構函式。SAPI Struct 提供 SAPI 指標中列出的所有方法,可取得 ::sapi::v::Ptr 物件,用於沙箱化程式庫呼叫。

以下程式碼片段顯示啟動的結構,然後傳遞至 zlib 範例中的沙箱函式呼叫:

sapi::v::Struct<sapi::zlib::z_stream> strm;

if (ret = api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
                             version.PtrBefore(), sizeof(sapi::zlib::z_stream));

如果現有 struct 包含指標,這些指標會指向 Sandboxee 中的位址。因此,您必須先轉移 Sandboxee 資料,才能讓主機程式碼存取。

SAPI 陣列

範本 ::sapi::v::Array 記錄在 var_array.h 中。這個範本提供兩個建構函式,一個可用於包裝現有的元素陣列,另一個則用於動態建立陣列。

下列程式碼片段 (取自 sum 範例) 說明如何使用建構函式包裝不屬於這個物件的陣列:

int arr[10];
sapi::v::Array<int> iarr(arr, ABSL_ARRAYSIZE(arr));

下列程式碼片段顯示用於動態建立陣列的建構函式範例:

sapi::v::Array<uint8_t> buffer(PNG_IMAGE_SIZE(*image.mutable_data()));

SAPI 陣列提供 SAPI 指標中列出的所有方法,可取得用於沙箱化程式庫呼叫的 ::sapi::v::Ptr 物件。