1. Elige un método de ejecutor de la zona de pruebas

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

Método 1: Independiente (ejecuta un objeto binario con la zona de pruebas ya habilitada)

Esta es la forma más sencilla de usar la zona de pruebas y es el método recomendado cuando quieres usar la zona de pruebas de un objeto binario completo para el que no tienes un código fuente. También es la forma más segura de usar la zona de pruebas, ya que no hay una inicialización sin zona de pruebas que podría tener efectos adversos.

En el siguiente fragmento de código, definimos la ruta del objeto binario que se someterá a una zona de pruebas y los argumentos que debemos pasar a una llamada de sistema ejecutable. 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 superior. 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 ejecutor son estático y herramienta.

#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: Forkserver de Sandbox2: Indica al ejecutor cuándo debe establecerse una zona de pruebas

Este método ofrece la flexibilidad de no incluir la zona de pruebas durante la inicialización y, luego, elegir cuándo ingresar a la zona de pruebas llamando a ::sandbox2::Client::SandboxMeHere(). Es necesario que puedas definir en el código cuándo quieres comenzar la zona de pruebas y que debe ser de un solo subproceso (puedes consultar por qué en las Preguntas frecuentes).

En el siguiente fragmento de código, usamos el mismo código que se describe en el método 1 más arriba. Sin embargo, para permitir que el programa se ejecute sin zona de pruebas durante la inicialización, llamaremos 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 Sandboxee la notifique, tenemos que crear una instancia de ::sandbox2::Client, configurar la comunicación entre el ejecutor y la Sandboxee, y luego notificar al ejecutor que finalizó nuestra inicialización y que queremos comenzar la zona de pruebas ahora 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 ejecutor es crc4, en el que crc4bin.cc es el elemento Sandboxee y notifica al ejecutor (crc4sandbox.cc) cuando debe ingresar a la zona de pruebas.

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

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

El ejecutor enviará una solicitud de bifurcación a tu objeto binario, que realizará el tipo fork() (a través de ::sandbox2::ForkingClient::WaitAndFork()). El proceso recién creado estará listo para una zona 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 aplicable solo en algunos casos específicos; por ejemplo, cuando tienes requisitos de memoria estrictos. Te beneficiarás con COW, pero la desventaja es que no existe una ASLR real. Otro ejemplo de uso típico sería cuando Sandboxee tiene una inicialización prolongada con uso intensivo de CPU que se puede ejecutar antes de que se procesen los datos que no son de confianza.

Para ver un ejemplo de este método ejecutor, consulta custom_fork.