1. اختيار طريقة تنفيذ في وضع الحماية
يبدأ وضع الحماية باستخدام برنامج تنفيذي (راجِع Sandbox Executor)، وهو المسؤول عن تشغيل Sandboxee. يحتوي ملف العنوان executor.h على واجهة برمجة التطبيقات اللازمة لهذا الغرض. تتسم واجهة برمجة التطبيقات بالمرونة الشديدة وتتيح لك اختيار ما يناسب حالة الاستخدام. تصف الأقسام التالية الأساليب الثلاثة المختلفة التي يمكنك الاختيار من بينها.
الطريقة 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: Forkserver في Sandbox2 - تحديد وقت وضع التنفيذ في وضع الحماية
توفّر هذه الطريقة المرونة في عدم استخدام وضع الحماية أثناء عملية التهيئة، ثم اختيار وقت تفعيل وضع الحماية من خلال استدعاء ::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::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 عملية إعداد طويلة تتطلّب الكثير من وحدة المعالجة المركزية ويمكن تنفيذها قبل معالجة البيانات غير الموثوق بها.
للاطّلاع على مثال على طريقة التنفيذ هذه، راجِع custom_fork.