1. 選擇沙箱執行器方法

沙箱作業會從執行 Sandboxee 的執行者開始 (請參閱「沙箱執行程式」)。executor.h 標頭檔案包含這項作業所需的 API。這個 API 非常有彈性,可讓您挑選最適合自身用途的 API。以下各節將說明 3 種可供選擇的方法。

方法 1:獨立 - 執行已啟用沙箱功能的二進位檔

這是使用沙箱最簡單的方法,當您想要對沒有原始碼的整個二進位檔進行沙箱時,建議使用這個方法。這也是使用沙箱最安全的方式,因為沒有任何沙箱初始化作業可能導致不良影響。

在下列程式碼片段中,我們會定義要採用沙箱機制的二進位檔路徑,以及必須傳遞至執行系統呼叫的引數。如 executor.h 標頭檔案中,我們未指定 envp 的值,因此會從父項程序複製環境。請注意,第一個引數一律是要執行的程式名稱,我們的程式碼片段不會定義任何其他引數。

這個執行器方法的範例包括:靜態工具

#include "sandboxed_api/sandbox2/executor.h"

std::string path = "path/to/binary";
std::vector<std::string> args = {path};  // args[0] will become the sandboxed
                                         // process' argv[0], typically the
                                         // path to the binary.
auto executor = absl::make_unique<sandbox2::Executor>(path, args);

方法 2: Sandbox2 Forkserver – 告知執行者何時要採用沙箱機制

這個方法可靈活地在初始化期間解除沙箱機制,然後呼叫 ::sandbox2::Client::SandboxMeHere() 來選擇進入沙箱模式的時機。要求在要開始沙箱時,能夠在程式碼中定義,且必須為單執行緒 (詳情請參閱常見問題)。

在下方的程式碼片段中,我們使用的是上方方法 1 所述的程式碼。不過,為了允許程式在初始化期間,以無沙箱的方式執行,我們呼叫 set_enable_sandbox_before_exec(false)

#include "sandboxed_api/sandbox2/executor.h"

std::string path = "path/to/binary";
std::vector<std::string> args = {path};
auto executor = absl::make_unique<sandbox2::Executor>(path, args);
executor->set_enable_sandbox_before_exec(false);

由於執行者現在已經停用沙箱,直到沙箱通知為止,因此我們必須建立 ::sandbox2::Client 執行個體,設定執行者和 Sandboxee 之間的通訊,然後通知執行者初始化完成,我們要呼叫 sandbox2_client.SandboxMeHere() 以開始沙箱。

// main() of sandboxee
int main(int argc, char** argv) {
  gflags::ParseCommandLineFlags(&argc, &argv, false);

  // Set-up the sandbox2::Client object, using a file descriptor (1023).
  sandbox2::Comms comms(sandbox2::Comms::kSandbox2ClientCommsFD);
  sandbox2::Client sandbox2_client(&comms);
  // Enable sandboxing from here.
  sandbox2_client.SandboxMeHere();
  …

這個執行者方法的例子是 crc4,其中 crc4bin.cc 是 Sandboxee,並在應進入沙箱時通知執行者 (crc4sandbox.cc)。

方法 3:自訂 Forkserver – 準備二進位檔、自行等待分支要求和沙箱

這個模式可讓您啟動二進位檔、為沙箱做好準備,並在二進位檔生命週期的特定時刻提供執行程式。

執行程式會將分支要求傳送至您的二進位檔,該二進位檔是透過 ::sandbox2::ForkingClient::WaitAndFork() fork() 傳送。新建立的程序即可與 ::sandbox2::Client::SandboxMeHere() 採用沙箱機制。

#include "sandboxed_api/sandbox2/executor.h"

// Start the custom ForkServer
std::string path = "path/to/binary";
std::vector<std::string> args = {path};
auto fork_executor = absl::make_unique<sandbox2::Executor>(path, args);
fork_executor->StartForkServer();

// Initialize Executor with Comms channel to the ForkServer
auto executor = absl::make_unique<sandbox2::Executor>(
    fork_executor->ipc()->GetComms());

請注意,這個模式相當複雜,僅適用於少數特定情況 (例如記憶體需求有限時)。您將享有 COW 的好處,但缺點是沒有真正的 ASLR。另一個典型的使用例子是,沙箱在處理不受信任的資料前,執行長時間且大量使用 CPU 的初始化作業。

如需此執行器方法的範例,請參閱 custom_fork