Exemplos

Informações gerais

Preparamos alguns exemplos para demonstrar como usar o Sandbox2 em diferentes cenários e como escrever políticas.

Você pode encontrá-los em //sandboxed_api/sandbox2/examples. Veja abaixo explicações detalhadas.

CRC4

O exemplo de CRC4 é um cálculo intencionalmente com bugs de uma soma de verificação CRC4, que demonstra como colocar outro programa no sandbox e como se comunicar com ele.

  • crc4bin.cc: o programa que queremos colocar no sandbox (ou seja, o sandboxee).
  • crc4sandbox.cc: o programa de sandbox que o executará (ou seja, o executor).

Como funciona:

  1. O executor inicia o Sandboxee pelo caminho de arquivo usando ::sandbox2::GetDataDependencyFilePath().
  2. O executor envia entradas ao sandbox pelo canal de comunicação Comms usando SendBytes().
  3. O sandboxee calcula o CRC4 e envia as respostas de volta ao executor pelo canal de comunicação Comms, que o recebe com RecvUint32().

Se o programa fizer qualquer chamada de sistema que não seja comunicação (read() e write()), ele será encerrado devido a uma violação da política.

static

O exemplo estático mostra como colocar no sandbox um binário vinculado estaticamente, como um binário de terceiros para o qual você não tem a origem, ou seja, que não sabe que ele será colocado no sandbox.

  • static_bin.cc: o sandboxee é um binário C estático que converte texto ASCII de entrada padrão para maiúsculas.
  • static_sandbox.cc: o executor com a política, os limites e o uso de um descritor de arquivo para a entrada do Sandboxee.

Como funciona:

  1. O executor inicia o Sandboxee pelo caminho do arquivo usando GetDataDependencyFilepath, assim como para CRC4.
  2. Ele define limites, abre um descritor de arquivo em /proc/version e o marca para ser mapeado no sandboxee com MapFd.
  3. A política permite que algumas chamadas do sistema (open) retornem um erro (ENOENT) em vez de serem interrompidas devido a uma violação da política. Isso pode ser útil ao colocar um programa de terceiros no sandbox, em que não podemos modificar quais chamadas do sistema são feitas, portanto, podemos fazê-las falhar normalmente.

Ferramenta

O exemplo da ferramenta é uma ferramenta para desenvolver suas próprias políticas e testar as APIs da Sandbox2, além de uma demonstração dos recursos.

  • sandbox2tool.cc: o executor demonstrando o seguinte:
    • como executar outro binário no sandbox,
    • como configurar verificações do sistema de arquivos e
    • como o executor pode executar o sandboxee de forma assíncrona para ler a saída progressivamente.

Experimente fazer o seguinte:

Bazel

bazel run //sandboxed_api/sandbox2/examples/tool:sandbox2tool -- \
--sandbox2tool_resolve_and_add_libraries \
--sandbox2tool_additional_bind_mounts /etc \
/bin/cat /etc/hostname

CMake + Ninja

cd build-dir
ninja sandbox2_sandbox2tool && \
./sandbox2_sandbox2tool \
--sandbox2tool_resolve_and_add_libraries \
--sandbox2tool_additional_bind_mounts /etc \
/bin/cat /etc/hostname

Google3 (Blaze)

blaze run //third_party/sandboxed_api/sandbox2/examples/tool:sandbox2tool -- \
 --sandbox2tool_resolve_and_add_libraries \
 --sandbox2tool_additional_bind_mounts /etc \
 /bin/cat /etc/hostname

Sinalizações:

  • --sandbox2tool_resolve_and_add_libraries para resolver e ativar as bibliotecas necessárias para o sandboxee.
  • --sandbox2tool_additional_bind_mounts <PATHS> para disponibilizar mais diretórios para o sandboxee.
  • --sandbox2tool_keep_env para manter as variáveis de ambiente atuais
  • --sandbox2tool_redirect_fd1 para receber o STDOUT_FILENO (1) do sandbox e gerar localmente.
  • --sandbox2tool_cpu_timeout para definir o tempo limite da CPU em segundos.
  • --sandbox2tool_walltime_timeout para definir o tempo limite do tempo decorrido em segundos.
  • --sandbox2tool_file_size_creation_limit: para definir o tamanho máximo dos arquivos criados.
  • --sandbox2tool_cwd para definir o diretório de trabalho atual do sandbox.

custom_fork

O exemplo custom_fork demonstra como criar um sandbox que vai inicializar o binário e aguardar solicitações fork() do executor pai.

Esse modo oferece um desempenho potencialmente maior em relação a outros tipos de sandbox. Nesse caso, a criação de novas instâncias de sandboxes não exige a execução de novos binários, apenas bifurcando os já existentes.

  • custom_fork_bin.cc: o servidor de bifurcação personalizado, que recebe solicitações para fork() (via Client::WaitAndFork) para gerar novos sandboxes.
  • custom_fork_sandbox.cc: o executor, que inicia um servidor de bifurcação personalizado. Em seguida, ele envia solicitações para ele (por novos executores) para gerar (usando fork()) novos sandboxes.

rede

O namespace da rede, que é ativado por padrão, impede que o processo em sandbox se conecte com o mundo externo. Este exemplo demonstra como lidar com esse problema.

Uma conexão é inicializada dentro do executor, e o soquete resultante é transmitido via ::sandbox2::Comms::SendFD(). O sandboxee recebe o soquete usando ::sandbox2::Comms::RecvFD() e pode usá-lo para trocar os dados normalmente.

  • network_bin.cc: o programa que queremos colocar no sandbox (ou seja, o sandboxee).
  • network_sandbox.cc: o programa de sandbox que o executa (ou seja, o executor).

network_proxy

Este exemplo demonstra uma maneira alternativa de lidar com um namespace de rede. Internamente, ela funciona exatamente da mesma maneira que o exemplo acima, mas é exposta como uma API mais conveniente.

O sandboxee pode estabelecer uma conexão de rede de duas maneiras:

  • automático: instalando um gerenciador automático e emitindo chamadas de conexão regulares.
  • manual: ao receber um NetworkProxyClient e usar diretamente NetworkProxyClient::Connect.

Este exemplo mostra os dois métodos. O modo automático é usado quando a flag connect_with_handler está definida. Caso contrário, o modo manual será usado.