1. 選擇沙箱執行器方法
沙箱作業會從執行器 (請參閱「沙箱執行器」) 開始,負責執行 Sandboxee。executor.h 標頭檔案包含此用途所需的 API。這項 API 非常彈性,可讓您選擇最適合自己用途的項目。以下各節說明瞭 3 種不同的方法,您可以選擇其中一種。
方法 1:獨立執行 - 執行已啟用沙箱的二進位檔
這是最簡單的沙箱化方式,如果您想沙箱化整個沒有原始碼的二進位檔,建議使用這個方法。這也是最安全的沙箱機制使用方式,因為沒有可能產生負面影響的未沙箱化初始化作業。
在下列程式碼片段中,我們會定義要進行沙箱處理的二進位檔路徑,以及必須傳遞至 execve 系統呼叫的引數。如您在 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);
由於執行器現在會停用沙箱,直到 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」。