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.
Dependencias de la compilación
Se deben instalar las siguientes dependencias 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: GCC 6 (se prefiere la versión 7 o posterior) o Clang 7 (o posterior)
- Para generar de forma automática archivos de encabezado: vinculaciones de Python de Clang
- Python 3.5 o versiones posteriores
- Bazel versión 2.2.0 o CMake versión 3.12 o versiones posteriores
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.), 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.listwget -qO - https://releases.bazel.build/bazel-release.pub.gpg | sudo apt-key add -sudo apt-get updatesudo apt-get install -qy build-essential linux-libc-dev bazel python3 \ python3-pip libclang-devpip3 install clang
Gentoo
Opciones de kernel requeridas:
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-pythonUsa CMake
CMake es un sistema de metacomilación popular 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-devpip3 install absl-py clang
Gentoo
Opciones de kernel requeridas:
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-pythonProceso de desarrollo
Para crear una biblioteca de C/C++ en zona de pruebas, deberás preparar dos elementos para tu proyecto:
- La biblioteca en zona de pruebas
- El código de host que usará la funcionalidad expuesta por tu biblioteca en zona de pruebas SAPI generará automáticamente el objeto SAPI y el stub de RPC durante el proceso de compilación.
Es posible que conozcas zlib de los ejemplos de Sandbox2. Aquí se creó una zona de pruebas para un programa completo (zpipe.c) . En los siguientes pasos, aprenderás a usar SAPI para crear una zona de pruebas para la biblioteca zlib y usar la biblioteca en zona de pruebas.
1. Decide qué funciones son necesarias
Si observas el código de host de zlib
(main_zlib.cc),
puedes 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_(): Para inicializar la compresióndeflate(): Para realizar la operación de compresión en el fragmento de datosdeflateEnd(): 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 estrategia posible es comenzar con el código de host y usar la biblioteca sin zona de pruebas. Luego, en un segundo paso, podrías generar la biblioteca en zona de pruebas y adaptar el código de host para usar las llamadas a funciones en zona de pruebas.
2. Escribe la regla de compilación 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 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 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",
)
Como resultado, se genera la biblioteca de zlib en zona de pruebas. El resultado es el objeto SAPI que se puede incluir en el código de host y se puede usar para comunicarse con la biblioteca en zona de pruebas mediante llamadas a RPC.
En este ejemplo, se usa la configuración predeterminada de la zona de pruebas que proporciona
DefaultConfig
(sapi::SandboxConfig::DefaultConfig()).
3. Escribe o cambia el código de host
Ahora es el momento de incorporar la biblioteca SAPI generada en el código de host.
Crea la zona de pruebas
Usa sapi::zlib::ZlibSandbox sandbox; para crear un objeto de zona de pruebas.
Usa sapi::zlib::ZlibApi api(&sandbox); para crear una instancia del objeto SAPI y, de esta manera,
hacer que las funciones en zona de pruebas estén disponibles para su uso.
Para personalizar la política, las marcas, las variables de entorno o los límites de la zona de pruebas, comienza
con sapi::SandboxConfig::DefaultConfig(), modifica los campos relevantes (con
sapi::Sandbox2Config::DefaultPolicyBuilder(),
sapi::SandboxConfig::DefaultFlags(), o
sapi::SandboxConfig::DefaultEnvironmentVariables() para que se conserven los parámetros de configuración de referencia)
y pasa el sapi::SandboxConfig al constructor de la zona de pruebas:
sapi::SandboxConfig config = sapi::SandboxConfig::DefaultConfig();
config.sandbox2.policy = sapi::Sandbox2Config::DefaultPolicyBuilder()
.AddFile("/path/to/file")
.BuildOrDie();
auto flags = sapi::SandboxConfig::DefaultFlags();
flags["my_flag"] = "value";
config.command_line_flags = std::move(flags);
sapi::zlib::ZlibSandbox sandbox(std::move(config));
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, donde
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 generado automáticamente por 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 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();
Usa transacciones de SAPI
SAPI aísla el código de host de la biblioteca en zona de pruebas y le da al llamador la capacidad de reiniciar o anular las solicitudes de procesamiento de datos problemáticas. La transacción de SAPI va un paso más allá y repite automáticamente los procesos fallidos.
Consulta la página Transacciones de SAPIpara obtener más detalles.
Ejemplos
En Ejemplos, puedes encontrar algunas bibliotecas, ya preparadas por el equipo de SAPI.