1. Memilih Metode Sandbox Executor
Sandbox dimulai dengan executor (lihat Sandbox Executor), yang bertanggung jawab untuk menjalankan Sandboxee. File header executor.h berisi API yang diperlukan untuk tujuan ini. API ini sangat fleksibel dan memungkinkan Anda memilih opsi yang paling sesuai dengan kasus penggunaan Anda. Bagian berikut menjelaskan 3 metode berbeda yang dapat Anda pilih.
Metode 1: Mandiri – Mengeksekusi biner dengan sandbox yang sudah diaktifkan
Ini adalah cara paling sederhana untuk menggunakan sandbox dan merupakan metode yang direkomendasikan jika Anda ingin membuat sandbox untuk seluruh biner yang tidak memiliki kode sumber. Cara ini juga merupakan cara paling aman untuk menggunakan sandbox, karena tidak ada inisialisasi tanpa sandbox yang dapat menimbulkan efek buruk.
Dalam cuplikan kode berikut, kita menentukan jalur biner yang akan di-sandbox
dan argumen yang harus kita teruskan ke syscall execve. Seperti yang dapat Anda lihat di file header
executor.h, kami tidak menentukan nilai untuk envp
dan oleh karena itu menyalin lingkungan dari proses induk. Ingat, argumen pertama selalu berupa
nama program yang akan dieksekusi, dan cuplikan kita tidak menentukan argumen
lain.
Contoh metode executor ini adalah: static dan 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);
Metode 2: Sandbox2 Forkserver – Memberi tahu eksekutor kapan harus di-sandbox
Metode ini menawarkan fleksibilitas untuk tidak di-sandbox selama inisialisasi, dan kemudian memilih waktu untuk memasuki sandbox dengan memanggil ::sandbox2::Client::SandboxMeHere()
. Anda harus dapat menentukan dalam kode kapan Anda ingin memulai sandbox, dan sandbox harus berupa thread tunggal (baca alasannya di FAQ).
Dalam cuplikan kode berikut, kita menggunakan kode yang sama seperti yang diuraikan dalam Metode 1 di atas. Namun, agar program dapat dieksekusi tanpa sandbox
selama inisialisasi, kita memanggil 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);
Karena executor kini memiliki sandbox yang dinonaktifkan hingga diberi tahu oleh
Sandboxee, kita harus membuat instance ::sandbox2::Client
, menyiapkan
komunikasi antara executor dan Sandboxee, lalu memberi tahu executor
bahwa inisialisasi kita telah selesai dan kita ingin memulai sandbox sekarang dengan
memanggil 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();
…
Contoh metode eksekutor ini adalah
crc4, dengan crc4bin.cc
adalah
Sandboxee dan memberi tahu eksekutor (crc4sandbox.cc
) saat harus memasuki
sandbox.
Metode 3: Forkserver Kustom – Siapkan biner, tunggu permintaan fork, dan sandbox sendiri
Mode ini memungkinkan Anda memulai biner, menyiapkan biner untuk sandbox, dan, pada saat tertentu dalam siklus proses biner, membuatnya tersedia untuk eksekutor.
Eksekutor akan mengirim permintaan fork ke biner Anda, yang akan fork()
(melalui
::sandbox2::ForkingClient::WaitAndFork()
). Proses yang baru dibuat akan
siap di-sandbox dengan ::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());
Perlu diingat bahwa mode ini cukup rumit dan hanya berlaku dalam beberapa kasus tertentu; misalnya, saat Anda memiliki persyaratan memori yang ketat. Anda akan mendapatkan manfaat dari COW, tetapi memiliki kekurangan karena tidak ada ASLR yang sebenarnya. Contoh penggunaan umum lainnya adalah saat Sandboxee memiliki inisialisasi yang panjang dan intensif CPU yang dapat dijalankan sebelum data yang tidak tepercaya diproses.
Untuk contoh metode executor ini, lihat custom_fork.