1. 選擇沙箱執行器方法

沙箱作業會從執行器 (請參閱「沙箱執行器」) 開始,負責執行 Sandboxeeexecutor.h 標頭檔案包含此用途所需的 API。這項 API 非常彈性,可讓您選擇最適合自己用途的項目。以下各節說明瞭 3 種不同的方法,您可以選擇其中一種。

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

這是最簡單的沙箱化方式,如果您想沙箱化整個沒有原始碼的二進位檔,建議使用這個方法。這也是最安全的沙箱機制使用方式,因為沒有可能產生負面影響的未沙箱化初始化作業。

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

這類執行器方法包括:statictool

#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);

由於執行器現在會停用沙箱,直到 Sandboxee 通知為止,因此我們必須建立 ::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 - 準備二進位檔、等待 fork 要求,並自行沙箱化

這個模式可讓您啟動二進位檔、準備進行沙箱化,並在二進位檔生命週期的特定時刻,將其提供給執行器。

執行器會將分叉要求傳送至二進位檔,該二進位檔會透過 fork() (經由 ::sandbox2::ForkingClient::WaitAndFork()) 建立新程序,並準備好透過 ::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。另一個常見的用法範例是,Sandboxee 有耗用大量 CPU 的長時間初始化作業,可在處理不受信任的資料前執行。

如需這個執行器方法的範例,請參閱「custom_fork」。