開始使用 Sandboxed API

在這個網頁中,您將瞭解如何使用 Sandboxed API (SAPI) 建立自己的沙箱 C/C++ 程式庫。也可以做為標頭檔案中的範例和程式碼說明文件使用。

建構依附元件

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

  • 支援 UTS、IPC、使用者、PID 和網路命名空間的 Linux kernel
  • 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

熱托

必要核心選項:

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

熱托

必要核心選項:

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++ 程式庫設定沙箱,您必須為專案準備兩個項目:

您可能聽過整個程式 (zpipe.c) 的Sandbox2 範例中的 zlib。在後續步驟中,您將瞭解如何使用 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 會指示查看 zlib 程式庫的 WORKSPACE 檔案。

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 團隊準備的程式庫。