1. Elige un método de ejecución de zona de pruebas

La zona de pruebas comienza con un ejecutor (consulta Sandbox Executor), que es responsable de ejecutar el Sandboxee. El archivo de encabezado executor.h contiene la API necesaria para este propósito. La API es muy flexible y te permite elegir lo que mejor se adapte a tu caso de uso. En las siguientes secciones, se describen los 3 métodos diferentes entre los que puedes elegir.

Método 1: Independiente: Ejecuta un archivo binario con el aislamiento de zona de pruebas ya habilitado

Esta es la forma más sencilla de usar el aislamiento y es el método recomendado cuando deseas aislar un archivo binario completo del que no tienes el código fuente. También es la forma más segura de usar la zona de pruebas, ya que no hay inicialización sin zona de pruebas que pueda tener efectos adversos.

En el siguiente fragmento de código, definimos la ruta de acceso del archivo binario que se debe ejecutar en el sandbox y los argumentos que debemos pasar a una llamada al sistema execve. Como puedes ver en el archivo de encabezado executor.h, no especificamos un valor para envp y, por lo tanto, copiamos el entorno del proceso principal. Recuerda que el primer argumento siempre es el nombre del programa que se ejecutará, y nuestro fragmento no define ningún otro argumento.

Algunos ejemplos de este método de ejecución son static y 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);

Método 2: Servidor fork de Sandbox2: Indica al ejecutor cuándo debe estar en zona de pruebas

Este método ofrece la flexibilidad de no estar en un entorno de pruebas durante la inicialización y, luego, elegir cuándo ingresar al entorno de pruebas llamando a ::sandbox2::Client::SandboxMeHere(). Requiere que puedas definir en el código cuándo quieres iniciar la zona de pruebas y debe ser de un solo subproceso (lee por qué en las preguntas frecuentes).

En el siguiente fragmento de código, usamos el mismo código que se describió en el método 1 anterior. Sin embargo, para permitir que el programa se ejecute de forma no aislada durante la inicialización, llamamos a 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);

Como el ejecutor ahora tiene una zona de pruebas inhabilitada hasta que el Sandboxee le notifique, debemos crear una instancia de ::sandbox2::Client, configurar la comunicación entre el ejecutor y el Sandboxee, y, luego, notificar al ejecutor que finalizó nuestra inicialización y que queremos comenzar a usar la zona de pruebas llamando a 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();
  

Un ejemplo de este método de ejecutor es crc4, en el que crc4bin.cc es el Sandboxee y notifica al ejecutor (crc4sandbox.cc) cuándo debe ingresar al sandbox.

Método 3: Forkserver personalizado: Prepara un objeto binario, espera solicitudes de bifurcación y crea un entorno de pruebas por tu cuenta

Este modo te permite iniciar un objeto binario, prepararlo para el aislamiento y, en un momento específico del ciclo de vida del objeto binario, ponerlo a disposición del ejecutor.

El ejecutor enviará una solicitud de bifurcación a tu archivo binario, que fork() (a través de ::sandbox2::ForkingClient::WaitAndFork()). El proceso recién creado estará listo para ejecutarse en un entorno de pruebas con ::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());

Ten en cuenta que este modo es bastante complicado y solo se aplica en algunos casos específicos, por ejemplo, cuando tienes requisitos de memoria estrictos. Te beneficiarás de COW, pero tendrás la desventaja de que no hay una verdadera ASLR. Otro ejemplo de uso típico sería cuando el Sandboxee tiene una inicialización larga y que requiere mucha CPU que se puede ejecutar antes de que se procesen los datos no confiables.

Para ver un ejemplo de este método de ejecución, consulta custom_fork.