5. ارتباط با Sandboxee

به طور پیش فرض، مجری می تواند با Sandboxee از طریق توصیفگرهای فایل ارتباط برقرار کند. این ممکن است تمام چیزی باشد که به آن نیاز دارید، برای مثال اگر فقط می خواهید یک فایل را با Sandboxee به اشتراک بگذارید، یا خروجی استاندارد Sandboxee را بخوانید.

با این حال، شما به احتمال زیاد نیاز به منطق ارتباطی پیچیده تری بین اجراکننده و Sandboxee دارید. comms API (به فایل هدر comms.h مراجعه کنید) می تواند برای ارسال اعداد صحیح، رشته ها، بافرهای بایت، پروتوباف ها یا توصیفگرهای فایل استفاده شود.

به اشتراک گذاری توصیف کننده های فایل

با استفاده از Inter-Process Communication API (به 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 API

Sandbox2 یک API comms راحت ارائه می دهد. این یک راه ساده و آسان برای به اشتراک گذاشتن اعداد صحیح، رشته‌ها یا بافرهای بایت بین اجراکننده و Sandboxee است. در زیر چند قطعه کد وجود دارد که می توانید در مثال crc4 بیابید.

برای شروع کار با comms API، ابتدا باید شی comms را از شی Sandbox2 دریافت کنید:

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

هنگامی که شی comms در دسترس است، داده ها را می توان با استفاده از یکی از خانواده توابع Send* به Sandboxee ارسال کرد. می توانید نمونه ای از استفاده از comms API را در مثال 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 */
}

به اشتراک گذاری داده ها با بافرها

یکی دیگر از قابلیت‌های اشتراک‌گذاری داده، استفاده از بافر API برای اشتراک‌گذاری مقادیر زیادی از داده‌ها و جلوگیری از کپی‌های گران‌قیمتی است که بین اجراکننده و Sandboxee ارسال می‌شود.

مجری یک بافر، یا بر اساس اندازه و داده هایی که باید ارسال شود، یا مستقیماً از یک توصیفگر فایل ایجاد می کند و با استفاده از comms->SendFD() در اجراکننده و comms->RecvFD() در Sandboxee به 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 */
،

5. ارتباط با Sandboxee

به طور پیش فرض، مجری می تواند با Sandboxee از طریق توصیفگرهای فایل ارتباط برقرار کند. این ممکن است تمام چیزی باشد که به آن نیاز دارید، برای مثال اگر فقط می خواهید یک فایل را با Sandboxee به اشتراک بگذارید، یا خروجی استاندارد Sandboxee را بخوانید.

با این حال، شما به احتمال زیاد نیاز به منطق ارتباطی پیچیده تری بین اجراکننده و Sandboxee دارید. comms API (به فایل هدر comms.h مراجعه کنید) می تواند برای ارسال اعداد صحیح، رشته ها، بافرهای بایت، پروتوباف ها یا توصیفگرهای فایل استفاده شود.

به اشتراک گذاری توصیف کننده های فایل

با استفاده از Inter-Process Communication API (به 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 API

Sandbox2 یک API comms راحت ارائه می دهد. این یک راه ساده و آسان برای به اشتراک گذاشتن اعداد صحیح، رشته‌ها یا بافرهای بایت بین اجراکننده و Sandboxee است. در زیر چند قطعه کد وجود دارد که می توانید در مثال crc4 بیابید.

برای شروع کار با comms API، ابتدا باید شی comms را از شی Sandbox2 دریافت کنید:

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

هنگامی که شی comms در دسترس است، داده ها را می توان با استفاده از یکی از خانواده توابع Send* به Sandboxee ارسال کرد. می توانید نمونه ای از استفاده از comms API را در مثال 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 */
}

به اشتراک گذاری داده ها با بافرها

یکی دیگر از قابلیت‌های اشتراک‌گذاری داده، استفاده از بافر API برای اشتراک‌گذاری مقادیر زیادی از داده‌ها و جلوگیری از کپی‌های گران‌قیمتی است که بین اجراکننده و Sandboxee ارسال می‌شود.

مجری یک بافر، یا بر اساس اندازه و داده هایی که باید ارسال شود، یا مستقیماً از یک توصیفگر فایل ایجاد می کند و با استفاده از comms->SendFD() در اجراکننده و comms->RecvFD() در Sandboxee به 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 */