Comienza a usar la API de Sandboxed

En esta página, aprenderás a crear tu propia biblioteca de C/C++ en zona de pruebas con la API de Sandboxed (SAPI). Úsala como guía junto con los ejemplos y la documentación del código en los archivos de encabezado.

Compila dependencias

Las siguientes dependencias deben estar instaladas en el sistema:

  • Kernel de Linux con compatibilidad para UTS, IPC, usuario, PID y espacios de nombres de red
  • Encabezados de la API del espacio de usuario de Linux
  • Para compilar tu código, necesitas GCC 6 (se recomienda la versión 7 o posterior) o Clang 7 (o posterior).
  • Para generar automáticamente archivos de encabezado: vinculaciones de Clang Python
  • Python 3.5 o una versión posterior
  • Bazel versión 2.2.0 o CMake versión 3.12 o posterior
    • Solo CMake: GNU Make o una versión de los encabezados de la biblioteca libcap y una herramienta de compilación como Ninja (recomendado).

Usa Bazel

Bazel es el sistema de compilación recomendado y el más fácil de integrar.

Nuestra documentación usa el compilador Clang. Si necesitas una cadena de herramientas específica (p. ej., compilador, vinculador, etcétera), consulta la documentación de Bazel para obtener información sobre cómo cambiar la cadena de herramientas del compilador predeterminado.

Debian 10 (Buster)

Para instalar las dependencias de compilación, haz lo siguiente:

echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | \
  sudo tee /etc/apt/sources.list.d/bazel.list
wget -qO - https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install -qy build-essential linux-libc-dev bazel python3 \
  python3-pip libclang-dev
pip3 install clang

Gentoo

Opciones del kernel requeridas:

General setup  --->
-*- Namespaces support
[*]   UTS namespace
[*]   IPC namespace
[*]   User namespace (EXPERIMENTAL)
[*]   PID Namespaces
[*]   Network namespace

Para instalar las dependencias de compilación, haz lo siguiente:

emerge dev-util/bazel dev-python/typing dev-python/clang-python

Cómo usar CMake

CMake es un sistema de compilación meta de código abierto popular que genera archivos de proyecto para herramientas de compilación como Ninja o Make.

Debian 10 (Buster)

Para instalar las dependencias de compilación, haz lo siguiente:

sudo apt-get install -qy build-essential linux-libc-dev cmake ninja-build \
  python3 python3-pip libclang-dev libcap-dev
pip3 install absl-py clang

Gentoo

Opciones del kernel requeridas:

General setup  --->
-*- Namespaces support
[*]   UTS namespace
[*]   IPC namespace
[*]   User namespace (EXPERIMENTAL)
[*]   PID Namespaces
[*]   Network namespace

Para instalar las dependencias de compilación, haz lo siguiente:

emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python

Proceso de desarrollo

Para aislar una biblioteca de C/C++, deberás preparar dos elementos para tu proyecto:

Es posible que conozcas zlib de los ejemplos de Sandbox2. Aquí se aisló un programa completo (zpipe.c). En los siguientes pasos, aprenderás a usar SAPI para aislar la biblioteca zlib en un entorno de pruebas y usar la biblioteca aislada en un entorno de pruebas.

1. Decide qué funciones son necesarias

Si observas el código del host de zlib (main_zlib.cc), verás que la funcionalidad de la herramienta es leer datos de stdin y usar la función deflate() de zlib para comprimir los datos hasta que se lea un marcador EOF. En total, el programa usa tres funciones de zlib:

  • deflateInit_(): Inicializar para la compresión
  • deflate(): Para realizar la operación de compresión en el fragmento de datos
  • deflateEnd(): Para finalizar la compresión y liberar las estructuras de datos asignadas de forma dinámica

En un ejemplo de la vida real, revisarías la biblioteca de C/C++ y decidirías qué funciones son necesarias. Una posible estrategia es comenzar con el código de host y usar la biblioteca sin aislamiento. Luego, en un segundo paso, podrías generar la biblioteca en zona de pruebas y adaptar el código del host para usar las llamadas a funciones en zona de pruebas.

2. Escribe la regla de compilación de sapi_library

Después de identificar las tres funciones de zlib que se necesitan de la biblioteca de zlib en zona de pruebas, puedes definir la regla de compilación en el archivo BUILD. La documentación de la regla de compilación sapi_library se encuentra en la página Reglas de compilación.

En el siguiente fragmento de código, se muestra la definición de sapi_library para el ejemplo de la SAPI de zlib. Con el atributo lib, se le indica a Bazel que busque la biblioteca zlib en el archivo WORKSPACE.

sapi_library(
    name = "zlib-sapi",
    srcs = [],
    hdrs = [],
    functions = [
        "deflateInit_",
        "deflate",
        "deflateEnd",
    ],
    lib = "@net_zlib//:zlib",
    lib_name = "Zlib",
    namespace = "sapi::zlib",
)

El resultado es que se genera la biblioteca zlib en zona de pruebas. El resultado es el objeto de la SAPI que se puede incluir en el código del host y se puede usar para comunicarse con la biblioteca en zona de pruebas a través de llamadas de RPC. La política de zona de pruebas que se usa en este ejemplo es la política predeterminada.

3. Cómo escribir o cambiar el código de anfitrión

Ahora es momento de incorporar la biblioteca de SAPI generada en el código del host.

Crea el espacio aislado

Usa sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create()); para crear un objeto de zona de pruebas.

Usa sapi::zlib::ZlibApi api(&sandbox); para crear una instancia del objeto de la SAPI y, de este modo, hacer que las funciones en zona de pruebas estén disponibles para su uso.

Usa tipos de SAPI

Los tipos de SAPI son tipos especiales en forma de clases de C++ que proporciona SAPI porque, a veces, los tipos C normales no funcionan.

El primer uso de un tipo de SAPI se puede observar en la declaración de strm, en la que se usa una estructura de SAPI: sapi::v::Struct<sapi::zlib::z_stream> strm;

El tipo de plantilla (sapi::zlib::z_stream) es un buen ejemplo de código que genera automáticamente la regla de compilación.

Consulta la página Variables para obtener más detalles.

Realiza llamadas a la API

Para llamar a defalteInit_, deflate o deflateEnd, usa el objeto SAPI. Si decides usar el enfoque de "cambio", debes asegurarte de que los parámetros de la función coincidan con los valores esperados.

Un ejemplo de cada una de las llamadas en el ejemplo de zlib:

  • api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
        version.PtrBefore(), sizeof(sapi::zlib::z_stream));
  • api.deflate(strm.PtrBoth(), flush);
  • api.deflateEnd(strm.PtrBoth()).IgnoreError();

Uso de transacciones de la SAPI

La SAPI aísla el código del host de la biblioteca en zona de pruebas y le brinda al llamador la capacidad de reiniciar o anular solicitudes problemáticas de procesamiento de datos. La transacción de la SAPI va un paso más allá y repite automáticamente los procesos fallidos.

Consulta la página de transacciones de la SAPI para obtener más detalles.

Ejemplos

En Ejemplos, puedes encontrar algunas bibliotecas que ya preparó el equipo de la SAPI.