1. בחירת שיטת ביצוע של Sandbox

Sandboxing מתחיל עם מנהל (ראה Sandbox Executor), שאחראי להפעלת Sandboxee. קובץ הכותרת executor.h מכיל את ה-API שנדרש למטרה זו. ה-API גמיש מאוד ומאפשר לכם לבחור מה הכי מתאים לתרחיש לדוגמה שלכם. בקטעים הבאים מתוארות 3 השיטות השונות שמהן אפשר לבחור.

שיטה 1: עצמאי – ביצוע קובץ בינארי כשהרצה בארגז חול כבר מופעלת

זוהי הדרך הפשוטה ביותר להשתמש בהרצה בארגז חול (sandboxing) והיא השיטה המומלצת כשרוצים לבצע הרצה בארגז חול (sandbox) של קובץ בינארי מלא שאין לכם קוד מקור עבורו. זו גם הדרך הבטוחה ביותר להשתמש בארגז החול, כי אין אתחול שלא הופעל בארגז חול שעלול להשפיע לרעה.

בקטע הקוד הבא, אנו מגדירים את הנתיב של הקובץ הבינארי להרצה בארגז החול ואת הארגומנטים שעלינו להעביר ל-syscall של הפעלה. כפי שניתן לראות בקובץ הכותרת 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);

שיטה 2: Sandbox2 Forkserver – אומרים למנהל המערכת מתי לעבור לארגז החול

השיטה הזו מאפשרת את הגמישות לבטל את הפעלת ארגז החול במהלך האתחול, ולאחר מכן לבחור מתי להיכנס לארגז חול על ידי קריאה ל-::sandbox2::Client::SandboxMeHere(). לשם כך נדרשת יכולת להגדיר בקוד כשאתם רוצים להתחיל לבצע הרצה בארגז חול (sandboxing) והוא צריך להיות עם שרשור יחיד (כדאי לקרוא על הסיבה לכך בשאלות הנפוצות).

בקטע הקוד הבא, אנו משתמשים באותו הקוד שמתואר בשיטה 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);

מכיוון שלחשבון ההפעלה יש עכשיו Sandbox מושבת עד שהוא יקבל הודעה מה-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.

שיטה 3: שרת Forkserver בהתאמה אישית – הכנת קובץ בינארי, המתנה לבקשות מזלג וארגז חול בעצמכם

מצב זה מאפשר לך להפעיל קובץ בינארי, להכין אותו להרצה בארגז חול (sandboxing) ולהפוך אותו לזמין למפעיל ברגע מסוים במחזור החיים של הקובץ הבינארי.

מנהל ההפעלה ישלח בקשת מזלג לקובץ הבינארי שלך, fork() (באמצעות ::sandbox2::ForkingClient::WaitAndFork()). התהליך החדש שייווצר יהיה מוכן להרצה בארגז חול (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.