開始使用 Sandboxed API

本頁面將說明如何使用 Sandboxed API (SAPI) 建立自己的 C/C++ 程式庫。請搭配標頭檔案中的範例和程式碼說明文件,將其做為指南。

建立依附元件

系統必須安裝下列依附元件:

  • 支援 UTS、IPC、使用者、PID 和網路命名空間的 Linux 核心
  • Linux 使用者空間 API 標頭
  • 如要編譯程式碼:GCC 6 (建議使用 7 以上版本) 或 Clang 7 (或更高版本)
  • 自動生成標頭檔:Clang Python 繫結
  • Python 3.5 以上版本
  • Bazel 2.2.0 版或 CMake 3.12 以上版本。
    • 僅限 CMake:GNU Make 或 libcap 程式庫標頭版本,以及建構工具,例如 Ninja (建議使用)。

使用 Bazel

建議使用 Bazel 建構系統,因為最容易整合。

我們的說明文件使用 Clang 編譯器。如需特定工具鍊 (例如編譯器、連結器等),請參閱 Bazel 說明文件,瞭解如何變更預設編譯器工具鍊。

Debian 10 (Buster)

如要安裝建構依附元件,請執行下列操作:

echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | \
  sudo tee /etc/apt/sources.list.d/bazel.list
wget -qO - https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install -qy build-essential linux-libc-dev bazel python3 \
  python3-pip libclang-dev
pip3 install clang

Gentoo

必要核心選項:

General setup  --->
-*- Namespaces support
[*]   UTS namespace
[*]   IPC namespace
[*]   User namespace (EXPERIMENTAL)
[*]   PID Namespaces
[*]   Network namespace

如要安裝建構依附元件,請執行下列操作:

emerge dev-util/bazel dev-python/typing dev-python/clang-python

使用 CMake

CMake 是熱門的開放原始碼中繼建構系統,可為 NinjaMake 等建構工具產生專案檔案。

Debian 10 (Buster)

如要安裝建構依附元件,請執行下列操作:

sudo apt-get install -qy build-essential linux-libc-dev cmake ninja-build \
  python3 python3-pip libclang-dev libcap-dev
pip3 install absl-py clang

Gentoo

必要核心選項:

General setup  --->
-*- Namespaces support
[*]   UTS namespace
[*]   IPC namespace
[*]   User namespace (EXPERIMENTAL)
[*]   PID Namespaces
[*]   Network namespace

如要安裝建構依附元件,請執行下列操作:

emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python

開發流程

如要將 C/C++ 程式庫設為沙箱,您必須為專案準備兩項項目:

您可能已在這個 Sandbox2 範例中看過 zlib,其中整個程式 (zpipe.c) 都經過沙箱處理。在下列步驟中,您將瞭解如何使用 SAPI 將 zlib 程式庫設為沙箱,並使用沙箱化程式庫。

1. 決定所需功能

查看 zlib 主機程式碼 (main_zlib.cc) 時,您會發現這項工具的功能是從 stdin 讀取資料,並使用 zlib 的 deflate() 函式壓縮資料,直到讀取 EOF 標記為止。這個程式總共使用了 zlib 的三個函式:

  • deflateInit_():初始化壓縮作業
  • deflate():對資料區塊執行壓縮作業
  • deflateEnd():結束壓縮並釋放動態分配的資料結構

在實際範例中,您會檢查 C/C++ 程式庫,並決定需要哪些函式。其中一種策略是從主機程式碼著手,並使用未經過沙箱處理的程式庫。接著,在第二個步驟中,您可以生成沙箱化程式庫,並調整主機程式碼,以使用沙箱化函式呼叫。

2. 編寫 sapi_library 建構規則

找出沙箱化 zlib 程式庫中所需的三個 zlib 函式後,您可以在 BUILD 檔案中定義建構規則。如要瞭解 sapi_library 建構規則,請參閱「建構規則」頁面。

以下程式碼片段顯示 zlib SAPI 範例的 sapi_library 定義。使用 lib 屬性時,Bazel 會在 WORKSPACE 檔案中尋找 zlib 程式庫。

sapi_library(
    name = "zlib-sapi",
    srcs = [],
    hdrs = [],
    functions = [
        "deflateInit_",
        "deflate",
        "deflateEnd",
    ],
    lib = "@net_zlib//:zlib",
    lib_name = "Zlib",
    namespace = "sapi::zlib",
)

系統就會產生沙箱化的 zlib 程式庫。輸出內容為 SAPI 物件,可納入主機程式碼,並用於透過 RPC 呼叫與沙箱程式庫通訊。本範例使用的沙箱政策為預設政策。

3. 撰寫或變更主機代碼

現在請將產生的 SAPI 程式庫併入主機程式碼。

建立沙箱

使用 sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create()); 建立沙箱物件。

使用 sapi::zlib::ZlibApi api(&sandbox); 例項化 SAPI 物件,即可使用沙箱函式。

使用 SAPI 類型

SAPI 型別是 SAPI 提供的 C++ 類別形式特殊型別,因為有時一般 C 型別無法運作。

您可以在 strm 的宣告中觀察到 SAPI 型別的首次使用,其中會使用 SAPI 結構體:sapi::v::Struct<sapi::zlib::z_stream> strm;

範本類型 (sapi::zlib::z_stream) 是建構規則自動產生的程式碼範例。

詳情請參閱變數頁面

發出 API 呼叫

如要呼叫 defalteInit_deflatedeflateEnd,請使用 SAPI 物件。如果決定使用「變更」方法,請務必確認函式參數符合預期值。

以下是 zlib 範例中每個呼叫的範例:

  • api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
        version.PtrBefore(), sizeof(sapi::zlib::z_stream));
  • api.deflate(strm.PtrBoth(), flush);
  • api.deflateEnd(strm.PtrBoth()).IgnoreError();

使用 SAPI 交易

SAPI 會將主機程式碼與沙箱化程式庫隔離,並讓呼叫端能夠重新啟動或中止有問題的資料處理要求。SAPI 交易更進一步,會自動重複執行失敗的程序。

如需更多詳細資料,請參閱 SAPI 交易頁面

範例

在「範例」下方,您可以找到 SAPI 團隊預先準備的幾個程式庫。