5. التواصل مع Sandboxee

يمكن للمسؤول التنفيذي تلقائيًا التواصل مع Sandboxee من خلال أدوات وصف الملفات. قد يكون هذا كل ما تحتاج إليه، على سبيل المثال إذا كنت تريد فقط مشاركة ملف مع Sandboxee أو اقرأ الإخراج العادي لـ Sandboxee.

ومع ذلك، أنت على الأرجح بحاجة إلى منطق اتصال أكثر تعقيدًا بين المدير التنفيذي وSandboxee. يمكن استخدام واجهة برمجة تطبيقات comms (راجِع ملف العنوان comms.h) لإرسال الأعداد الصحيحة أو السلاسل أو مخازن البايت الاحتياطية أو النماذج الأوّلية أو أدوات وصف الملفات.

مشاركة واصفات الملفات

باستخدام واجهة برمجة تطبيقات الاتصال بين العمليات (راجع ipc.h)، يمكنك استخدام MapFd() أو ReceiveFd():

  • يمكنك استخدام MapFd() لربط واصفات الملفات من أداة التنفيذ إلى تطبيق Sandboxee. يمكن استخدام ذلك لمشاركة ملف تم فتحه من تنفيذ الإجراء لاستخدامه في تطبيق Sandboxee. يمكن عرض مثال للاستخدام في الإعلان الثابت.

    // The executor opened /proc/version and passes it to the sandboxee as stdin
    executor->ipc()->MapFd(proc_version_fd, STDIN_FILENO);
    
  • يمكنك استخدام ReceiveFd() لإنشاء نقطة نهاية لإقران المقبس. ويمكن استخدام ذلك لقراءة الإخراج العادي أو الأخطاء العادية في Sandboxee. يمكن الاطّلاع على مثال على الاستخدام في الأداة.

    // The executor receives a file descriptor of the sandboxee stdout
    int recv_fd1 = executor->ipc())->ReceiveFd(STDOUT_FILENO);
    

استخدام واجهة برمجة تطبيقات comms

يوفر Sandbox2 واجهة برمجة تطبيقات للاتصالات ملائمة. هذه طريقة بسيطة وسهلة لمشاركة الأعداد الصحيحة أو السلاسل أو المخازن المؤقتة للبايت بين المنفّذ وSandboxee. في ما يلي بعض مقتطفات الرمز التي يمكنك العثور عليها في مثال crc4.

لبدء استخدام واجهة برمجة التطبيقات comms، يجب أولاً الحصول على كائن comms من كائن Sandbox2:

sandbox2::Comms* comms = s2.comms();

عند توفُّر كائن comms، يمكن إرسال البيانات إلى Sandboxee باستخدام إحدى عائلة دوال الإرسال*. يمكنك العثور على مثال لاستخدام واجهة برمجة تطبيقات comms في المثال crc4. يعرض مقتطف الرمز أدناه مقتطفًا من هذا المثال. يرسل منفذ التنفيذ unsigned char buf[size] باستخدام SendBytes(buf, size):

if (!(comms->SendBytes(static_cast<const uint8_t*>(buf), sz))) {
  /* handle error */
}

لتلقّي البيانات من Sandboxee، استخدِم إحدى وظائف Recv*. مقتطف الرمز أدناه هو مقتطف من مثال crc4. يتلقى التنفيذ المجموع الاختباري في عدد صحيح غير موقَّع 32 بت: uint32_t crc4;

if (!(comms->RecvUint32(&crc4))) {
  /* handle error */
}

مشاركة البيانات مع الموارد الاحتياطية

ومن الوظائف الأخرى لمشاركة البيانات استخدام واجهة برمجة التطبيقات للتخزين المؤقت لمشاركة كميات كبيرة من البيانات وتجنُّب النُسخ باهظة الثمن التي يتم إرسالها ذهابًا وإيابًا بين تطبيق التنفيذ وبرنامج Sandboxee.

ينشئ التنفيذ المخزن المؤقت، إما حسب الحجم والبيانات التي سيتم تمريرها، أو مباشرةً من أداة وصف الملف، ويمرره إلى Sandboxee باستخدام comms->SendFD() في المنفّذ وcomms->RecvFD() في Sandboxee.

في مقتطف الرمز أدناه، يمكنك رؤية جانب الجهة المنفّذة. يعمل وضع الحماية بشكل غير متزامن ويشارك البيانات عبر ذاكرة تخزين مؤقت مع تطبيق Sandboxee:

// start the sandbox asynchronously
s2.RunAsync();

// instantiate the comms object
sandbox2::Comms* comms = s2.comms();

// random buffer data we want to send
constexpr unsigned char buffer_data[] = /* random data */;
constexpr unsigned int buffer_dataLen = 34;

// create sandbox2 buffer
absl::StatusOr<std::unique_ptr<sandbox2::Buffer>> buffer =
     sandbox2::Buffer::CreateWithSize(1ULL << 20 /* 1Mib */);
std::unique_ptr<sandbox2::Buffer> buffer_ptr = std::move(buffer).value();

// point to the sandbox2 buffer and fill with data
uint8_t* buf = buffer_ptr‑>data();
memcpy(buf, buffer_data, buffer_data_len);

// send the data to the sandboxee
comms‑>SendFd(buffer_ptr‑>fd());

من جانب Sandboxee، يجب أيضًا إنشاء كائن مخزن مؤقت وقراءة البيانات من واصف الملف الذي أرسله المسؤول عن التنفيذ:

// establish the communication with the executor
int fd;
comms.RecvFD(&fd);

// create the buffer
absl::StatusOr<std::unique_ptr<sandbox2::Buffer>> buffer =
     sandbox2::Buffer::createFromFd(fd);

// get the data
auto buffer_ptr = std::move(buffer).value();
uint8_t* buf = buffer_ptr‑>data();

/* work with the buf object */