1. Choisir une méthode d'exécution de bac à sable

Le processus de bac à sable commence par un exécuteur (voir Exécuteur de bac à sable), qui est chargé d'exécuter le Sandboxee. Le fichier d'en-tête executor.h contient l'API nécessaire à cette fin. L'API est très flexible et vous permet de choisir ce qui convient le mieux à votre cas d'utilisation. Les sections suivantes décrivent les trois méthodes disponibles.

Méthode 1: Autonome – Exécuter un binaire avec le bac à sable déjà activé

Il s'agit de la méthode la plus simple pour utiliser le bac à sable. C'est également la méthode recommandée lorsque vous souhaitez mettre en bac à sable un binaire entier pour lequel vous n'avez pas de code source. Il s'agit également de la méthode la plus sûre pour utiliser le bac à sable, car aucune initialisation hors bac à sable ne peut avoir des effets néfastes.

Dans l'extrait de code suivant, nous définissons le chemin du binaire à mettre en bac à sable et les arguments à transmettre à un appel système "execve". Comme vous pouvez le voir dans le fichier d'en-tête executor.h, nous ne spécifions pas de valeur pour envp. Nous copions donc l'environnement à partir du processus parent. N'oubliez pas que le premier argument est toujours le nom du programme à exécuter et que notre extrait ne définit aucun autre argument.

static et tool sont des exemples de cette méthode d'exécution.

#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éthode 2: Serveur de transfert Sandbox2 – Indiquer à l'exécuteur quand le système doit lancer le bac à sable

Cette méthode offre la flexibilité de ne pas utiliser le bac à sable lors de l'initialisation, puis de choisir quand accéder au bac à sable en appelant ::sandbox2::Client::SandboxMeHere(). Vous devez être en mesure de définir dans le code à quel moment vous souhaitez lancer le bac à sable, et il doit être monothread (découvrez pourquoi dans les questions fréquentes).

Dans l'extrait de code suivant, nous utilisons le même code que celui décrit dans la méthode 1 ci-dessus. Toutefois, pour permettre au programme de s'exécuter hors bac à sable lors de l'initialisation, nous appelons 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);

Comme l'exécuteur dispose désormais d'un bac à sable désactivé jusqu'à ce que le bac à sable en soit informé, nous devons créer une instance ::sandbox2::Client, configurer la communication entre l'exécuteur et le bac à sable, puis avertir l'exécuteur que l'initialisation est terminée et que nous souhaitons lancer le bac à sable en appelant 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();
  …

crc4 est un exemple de cette méthode d'exécution. crc4bin.cc correspond au bac à sable et informe l'exécuteur (crc4sandbox.cc) lorsqu'il doit entrer dans le bac à sable.

Méthode 3: Custom Forkserver – Préparer un binaire, attendre les requêtes de duplication et bac à sable

Ce mode vous permet de démarrer un binaire, de le préparer pour le bac à sable et, à un moment spécifique du cycle de vie du binaire, de le rendre disponible pour l'exécuteur.

L'exécuteur enverra une requête de duplication à votre binaire, qui fork() (via ::sandbox2::ForkingClient::WaitAndFork()). Le processus nouvellement créé sera prêt à être exécuté en bac à sable avec ::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());

N'oubliez pas que ce mode est assez complexe et ne s'applique que dans quelques cas spécifiques, par exemple lorsque vous avez des besoins importants en mémoire. Vous bénéficierez de COW, mais l'inconvénient est qu'il n'y a pas de véritable ASLR. Autre exemple d'utilisation typique : lorsque le Sandboxee effectue une initialisation longue et exigeante en processeur, qui peut être exécutée avant que les données non fiables soient traitées.

Pour obtenir un exemple de cette méthode d'exécution, consultez custom_fork.