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

الطريقة الثانية: خادم 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() (عبر ::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.