Comienza a usar la API de Sandboxed

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

Dependencias de compilación

Las siguientes dependencias deben instalarse en el sistema:

  • Kernel de Linux con compatibilidad para UTS, IPC, usuario, PID y espacios de nombres de red
  • Encabezados de la API de espacio de usuario de Linux
  • Para compilar tu código, usa GCC 6 (se prefiere la versión 7 o superior) o Clang 7 (o versiones posteriores).
  • Para archivos de encabezado que se generan automáticamente: Vinculaciones de Clang para Python
  • Python 3.5 o posterior
  • Versión 2.2.0 de Bazel o CMake 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 es el más fácil de integrar.

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

Debian 10 (Buster)

Para instalar 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

Papúa

Las opciones de kernel son obligatorias:

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

Para instalar 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 popular sistema de metacompilación de código abierto que genera archivos de proyecto para herramientas de compilación como Ninja o Make.

Debian 10 (Buster)

Para instalar 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

Papúa

Las opciones de kernel son obligatorias:

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

Para instalar 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

A fin de hacer una zona de pruebas de una biblioteca C/C++, tendrás que preparar dos elementos para tu proyecto:

Es posible que estés familiarizado con los ejemplos de zlib de los ejemplos de Sandbox2 que se incluyen en la zona de pruebas de todo un programa (zpipe.c). En los siguientes pasos, aprenderás a usar SAPI para hacer una zona de pruebas de la biblioteca zlib y aprovecharla.

1. Decidir qué funciones son necesarias

Si observas el código de host de zlib (main_zlib.cc), podrás ver 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_(): Se inicializa para la compresión.
  • deflate(): Realiza la operación de compresión en el bloque de datos.
  • deflateEnd(): Finaliza la compresión y libera estructuras de datos asignadas de forma dinámica.

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

2. Escribe la regla de compilación sapi_library

Una vez que hayas identificado las tres funciones de zlib necesarias de la biblioteca de zlib de zona de pruebas, puedes definir la regla de compilación en el archivo BUILD. La documentación sobre la regla de compilación sapi_library se puede encontrar 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 zlib SAPI. 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 de zona de pruebas. El resultado es el objeto SAPI que se puede incluir en el código de host y usarse para comunicarse con la biblioteca de la zona de pruebas a través de llamadas RPC. La política de zona de pruebas que se usa en este ejemplo es la predeterminada.

3. Escribe o cambia el código de host

Llegó el momento de incorporar la biblioteca SAPI generada en el código de host.

Crea la zona de pruebas

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

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

Usa tipos de SAPI

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

El primer uso de un tipo SAPI se puede observar en la declaración de strm, en la que se usa una estructura 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 realizar llamadas 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 del 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();

Usa transacciones de SAPI

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

Consulta la página Transacciones de la API para obtener más detalles.

Ejemplos

En Ejemplos, encontrarás algunas bibliotecas, ya preparadas por el equipo de SAPI.