簡介
如「總覽」頁面所述,主機程式碼會對沙箱程式庫發出 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
物件。