На этой странице вы узнаете, как создать собственную изолированную библиотеку C/C++ с помощью Sandboxed API (SAPI). Используйте его в качестве руководства вместе с примерами и документацией по коду в заголовочных файлах.
Зависимости сборки
В системе должны быть установлены следующие зависимости:
- Ядро Linux с поддержкой UTS, IPC, пользователя, PID и сетевых пространств имен.
- Заголовки API пространства пользователя Linux
- Для компиляции кода: GCC 6 (рекомендуется версия 7 или более поздняя) или Clang 7 (или более поздняя версия).
- Для автоматического создания заголовочных файлов: Clang Python Bindings.
- Python 3.5 или более поздней версии;
- Bazel версии 2.2.0 или CMake версии 3.12 или более поздней.
Как использовать Bazel
Bazel – рекомендуемая система сборки, которую проще всего интегрировать.
В нашей документации используется компилятор Clang. Если вам нужна определенная цепочка инструментов (например, компилятор, компоновщик и т. д.), ознакомьтесь с документацией по Bazel, чтобы узнать, как изменить цепочку инструментов компилятора по умолчанию.
Debian 10 (Buster)
Чтобы установить зависимости сборки:
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
Требуемые параметры ядра:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Чтобы установить зависимости сборки:
emerge dev-util/bazel dev-python/typing dev-python/clang-pythonИспользование CMake
CMake – это популярная метасистема сборки с открытым исходным кодом, которая генерирует файлы проекта для таких инструментов сборки, как Ninja или Make.
Debian 10 (Buster)
Чтобы установить зависимости сборки:
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
Требуемые параметры ядра:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Чтобы установить зависимости сборки:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-pythonПроцесс разработки
Чтобы изолировать библиотеку C/C++, вам нужно подготовить для проекта два элемента:
- Библиотека изолированной среды
- Код хоста, который будет использовать функциональность, предоставляемую вашей изолированной библиотекой. SAPI автоматически сгенерирует объект SAPI и заглушку RPC во время сборки.
Возможно, вы уже знакомы с zlib из примеров Sandbox2. В этом случае в изолированную среду была помещена вся программа (zpipe.c). Ниже описано, как использовать SAPI, чтобы изолировать библиотеку zlib и воспользоваться изолированной библиотекой.
1. Решите, какие функции вам нужны
Если вы посмотрите код хоста zlib (main_zlib.cc), то увидите, что инструмент считывает данные из stdin и использует функцию deflate() из zlib для сжатия данных до тех пор, пока не будет прочитан маркер EOF.
Всего в программе используются три функции из zlib:
deflateInit_(): инициализация сжатия;deflate()– для выполнения операции сжатия над фрагментом данных.deflateEnd()– завершает сжатие и освобождает динамически выделенные структуры данных.
В реальном примере вы бы изучили библиотеку C/C++ и решили, какие функции вам нужны. Возможная стратегия – начать с кода хоста и использовать библиотеку без изолированной среды. Затем на втором этапе вы можете сгенерировать изолированную библиотеку и адаптировать код хоста для использования изолированных вызовов функций.
2. Напишите правило сборки sapi_library
Определив три функции zlib, которые нужны из изолированной библиотеки zlib, вы можете определить правило сборки в файле BUILD. Документацию по правилу сборки sapi_library можно найти на странице Правила сборки.
В приведенном ниже фрагменте кода показано определение sapi_library для примера SAPI zlib. С помощью атрибута lib Bazel получает указание искать библиотеку zlib в файле WORKSPACE.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
В результате будет создана изолированная библиотека zlib. На выходе получается объект SAPI, который можно включить в код хоста и использовать для связи с библиотекой в изолированной среде с помощью вызовов RPC.
В этом примере используется конфигурация изолированной среды по умолчанию, предоставленная функцией DefaultConfig
(sapi::SandboxConfig::DefaultConfig()).
3. Как написать или изменить код хоста
Теперь пришло время включить сгенерированную библиотеку SAPI в код хоста.
Как создать изолированную среду
Используйте sapi::zlib::ZlibSandbox sandbox;, чтобы создать объект песочницы.
Используйте sapi::zlib::ZlibApi api(&sandbox);, чтобы создать экземпляр объекта SAPI и сделать функции изолированной среды доступными для использования.
Чтобы настроить правила, флаги, переменные среды или ограничения изолированной среды, начните с sapi::SandboxConfig::DefaultConfig(), измените нужные поля (используя sapi::Sandbox2Config::DefaultPolicyBuilder(), sapi::SandboxConfig::DefaultFlags() или sapi::SandboxConfig::DefaultEnvironmentVariables(), чтобы сохранить базовые настройки) и передайте sapi::SandboxConfig конструктору изолированной среды:
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));
Использовать типы SAPI
Типы SAPI – это специальные типы в виде классов C++, которые предоставляет SAPI, поскольку обычные типы C иногда не работают.
Первое использование типа SAPI можно увидеть в объявлении strm, где используется структура SAPI: sapi::v::Struct<sapi::zlib::z_stream> strm;.
Тип шаблона (sapi::zlib::z_stream) – хороший пример кода, автоматически созданного правилом сборки.
Подробную информацию вы найдете на странице "Переменные".
Как выполнять вызовы API
Чтобы позвонить на номер defalteInit_, deflate или deflateEnd, используйте объект SAPI. Если вы решите использовать подход "изменить", убедитесь, что параметры функции соответствуют ожидаемым значениям.
Пример каждого вызова в примере 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();
Как использовать транзакции SAPI
SAPI изолирует код хоста от библиотеки в изолированной среде и позволяет вызывающей стороне перезапускать или прерывать запросы на обработку данных, которые вызывают проблемы. SAPI Transaction автоматически повторяет неудачные процессы.
Подробную информацию можно найти на странице транзакций SAPI.
Примеры
В разделе Examples (Примеры) вы найдете несколько библиотек, подготовленных командой SAPI.