本頁面將說明如何使用 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 以上版本。
使用 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 是熱門的開放原始碼中繼建構系統,可為 Ninja 或 Make 等建構工具產生專案檔案。
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++ 程式庫設為沙箱,您必須為專案準備兩項項目:
- 沙箱化程式庫
- 主機程式碼,將使用沙箱程式庫公開的功能。建構程序期間,SAPI 會自動為您產生 SAPI 物件和 RPC Stub。
您可能已在這個 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_
、deflate
或 deflateEnd
,請使用 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 交易頁面。