1. בחירה של שיטת הפעלה של ארגז חול
הסנדבוק מתחיל עם מפעיל (ראו Sandbox Executor), שאחראי להפעלת Sandboxee. קובץ הכותרת executor.h מכיל את ה-API שדרוש למטרה הזו. ה-API גמיש מאוד ומאפשר לכם לבחור את מה שהכי מתאים לתרחיש לדוגמה שלכם. בקטעים הבאים מתוארות 3 מתודולוגיות שונות שתוכלו לבחור מביניהן.
שיטה 1: עצמאית – הפעלת קובץ בינארי עם ארגז חול שכבר מופעל
זו הדרך הכי פשוטה להשתמש בארגון ארגז חול, והיא מומלצת כשרוצים להפעיל ארגז חול לקובץ בינארי שלם שאין לו קוד מקור. זו גם הדרך הבטוחה ביותר להשתמש בארגז חול, כי אין אתחול מחוץ לארגז החול שיכול לגרום להשפעות שליליות.
בקטע הקוד הבא, אנחנו מגדירים את הנתיב של הקובץ הבינארי שצריך להפעיל בארגז חול, ואת הארגומנטים שצריך להעביר לקריאת המערכת 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);
שיטה 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);
מכיוון שה-executor (תהליך ההפעלה) כולל עכשיו ארגז חול מושבת עד שהוא מקבל הודעה מה-Sandboxee (תהליך ארגז החול), אנחנו צריכים ליצור מופע של ::sandbox2::Client, להגדיר תקשורת בין ה-executor לבין ה-Sandboxee, ואז להודיע ל-executor שהאתחול שלנו הסתיים ואנחנו רוצים להתחיל להשתמש בארגז החול עכשיו על ידי קריאה ל-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 ומודיע ל-executor (crc4sandbox.cc) מתי הוא צריך להיכנס לארגז החול.
שיטה 3: שרת פורק מותאם אישית – הכנת קובץ בינארי, המתנה לבקשות פורק וארגז חול משלכם
במצב הזה אפשר להפעיל קובץ בינארי, להכין אותו להפעלת ארגז חול ובשלב מסוים במחזור החיים של הקובץ הבינארי, להפוך אותו לזמין למבצע.
התהליך יבצע fork של הבינארי שלכם וישלח בקשה ל-fork() (דרך ::sandbox2::ForkingClient::EnterForkLook()). התהליך החדש שנוצר יהיה מוכן להרצה בסביבת ארגז חול עם ::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.