5. Berkomunikasi dengan Sandboxee

Secara default, executor dapat berkomunikasi dengan Sandboxee melalui deskriptor file. Mungkin hanya ini yang Anda butuhkan, misalnya jika Anda hanya ingin membagikan file dengan Sandboxee, atau membaca output standar Sandboxee.

Namun, kemungkinan besar Anda memerlukan logika komunikasi yang lebih kompleks antara eksekutor dan Sandboxee. Comms API (lihat file header comms.h) dapat digunakan untuk mengirim bilangan bulat, string, buffer byte, protobuf, atau deskriptor file.

Membagikan Deskriptor File

Dengan menggunakan Inter-Process Communication API (lihat ipc.h), Anda dapat menggunakan MapFd() atau ReceiveFd():

  • Gunakan MapFd() untuk memetakan deskriptor file dari executor ke Sandboxee. Ini dapat digunakan untuk membagikan file yang dibuka dari executor untuk digunakan di Sandboxee. Contoh penggunaan dapat dilihat di static.

    // The executor opened /proc/version and passes it to the sandboxee as stdin
    executor->ipc()->MapFd(proc_version_fd, STDIN_FILENO);
    
  • GunakanReceiveFd() untuk membuat endpoint socketpair. Ini dapat digunakan untuk membaca output standar atau error standar Sandboxee. Contoh penggunaan dapat dilihat di alat.

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

Menggunakan comms API

Sandbox2 menyediakan comms API yang mudah. Ini adalah cara sederhana dan mudah untuk membagikan bilangan bulat, string, atau buffer byte antara executor dan Sandboxee. Berikut beberapa cuplikan kode yang dapat Anda temukan dalam contoh crc4.

Untuk mulai menggunakan Comms API, Anda harus mendapatkan objek comms dari objek Sandbox2 terlebih dahulu:

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

Setelah objek comms tersedia, data dapat dikirim ke Sandboxee menggunakan salah satu fungsi keluarga Send*. Anda dapat menemukan contoh penggunaan comms API dalam contoh crc4. Cuplikan kode di bawah menunjukkan kutipan dari contoh tersebut. Eksekutor mengirim unsigned char buf[size] dengan SendBytes(buf, size):

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

Untuk menerima data dari Sandboxee, gunakan salah satu fungsi Recv*. Cuplikan kode di bawah adalah kutipan dari contoh crc4. Eksekutor menerima checksum dalam bilangan bulat 32-bit tanpa tanda: uint32_t crc4;

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

Membagikan Data dengan Buffer

Fungsi berbagi data lainnya adalah menggunakan buffer API untuk berbagi data dalam jumlah besar dan menghindari salinan mahal yang dikirim bolak-balik antara executor dan Sandboxee.

Eksekutor membuat Buffer, baik berdasarkan ukuran dan data yang akan diteruskan, atau langsung dari deskriptor file, dan meneruskannya ke Sandboxee menggunakan comms->SendFD() di eksekutor dan comms->RecvFD() di Sandboxee.

Dalam cuplikan kode di bawah, Anda dapat melihat sisi executor. Sandbox berjalan secara asinkron dan membagikan data melalui buffer dengan 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());

Di sisi Sandboxee, Anda juga harus membuat objek buffer dan membaca data dari deskriptor file yang dikirim oleh executor:

// 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 */