۱. یک روش اجراکننده‌ی سندباکس انتخاب کنید

سندباکسینگ با یک اجراکننده (به بخش اجراکننده سندباکس مراجعه کنید) آغاز می‌شود که مسئول اجرای سندباکس است. فایل هدر executor.h شامل API مورد نیاز برای این منظور است. این API بسیار انعطاف‌پذیر است و به شما امکان می‌دهد تا انتخاب کنید که چه چیزی برای مورد استفاده شما بهتر عمل می‌کند. بخش‌های زیر ۳ روش مختلف را که می‌توانید از بین آنها انتخاب کنید، شرح می‌دهند.

روش ۱: مستقل - اجرای یک فایل باینری با فعال بودن قابلیت sandboxing

این ساده‌ترین روش برای استفاده از سندباکسینگ است و زمانی که می‌خواهید کل یک فایل باینری را که کد منبع آن را ندارید، سندباکس کنید، روش توصیه شده‌ای است. همچنین امن‌ترین راه برای استفاده از سندباکسینگ است، زیرا هیچ مقداردهی اولیه بدون سندباکس وجود ندارد که بتواند عوارض جانبی داشته باشد.

در قطعه کد زیر، مسیر فایل باینری که باید در جعبه شنی قرار گیرد و آرگومان‌هایی که باید به یک فراخوانی سیستمی execve ارسال کنیم را تعریف می‌کنیم. همانطور که در فایل هدر executor.h مشاهده می‌کنید، ما مقداری برای envp تعیین نکرده‌ایم و بنابراین محیط را از فرآیند والد کپی می‌کنیم. به یاد داشته باشید، اولین آرگومان همیشه نام برنامه‌ای است که باید اجرا شود و قطعه کد ما هیچ آرگومان دیگری را تعریف نمی‌کند.

نمونه‌هایی از این روش اجراکننده عبارتند از: static و tool .

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

روش ۲: Sandbox2 Forkserver – به مجری بگویید چه زمانی سندباکس شود

این روش انعطاف‌پذیری خارج شدن از حالت sandbox در طول مقداردهی اولیه و سپس انتخاب زمان ورود به sandboxing با فراخوانی ::sandbox2::Client::SandboxMeHere() را ارائه می‌دهد. این روش مستلزم آن است که بتوانید زمان شروع sandboxing را در کد تعریف کنید و باید تک‌رشته‌ای باشد (دلیل آن را در سوالات متداول بخوانید).

در قطعه کد زیر، ما از همان کدی که در روش ۱ در بالا توضیح داده شد استفاده می‌کنیم. با این حال، برای اینکه برنامه بتواند در حین مقداردهی اولیه به صورت بدون سندباکس اجرا شود، تابع 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 ) اطلاع می‌دهد که چه زمانی باید وارد sandbox شود.

روش ۳: سرور چنگال سفارشی - یک فایل باینری آماده کنید، منتظر درخواست‌های چنگال باشید و خودتان آن را در سندباکس قرار دهید

این حالت به شما امکان می‌دهد یک فایل باینری را شروع کنید، آن را برای sandbox آماده کنید و در یک لحظه خاص از چرخه حیات فایل باینری خود، آن را در دسترس مجری قرار دهید.

مجری یک درخواست fork به فایل باینری شما ارسال می‌کند که fork() را انجام می‌دهد (از طریق ::sandbox2::ForkingClient::EnterForkLook() ). فرآیند تازه ایجاد شده آماده‌ی sandbox شدن با ::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 مراجعه کنید.