На этой странице вы узнаете, как создать собственную изолированную библиотеку C/C++ с помощью Sandboxed API (SAPI). Используйте его в качестве руководства вместе с примерами и документацией по коду в заголовочных файлах.
Создание зависимостей
В системе должны быть установлены следующие зависимости:
- Ядро Linux с поддержкой пространств имен UTS, IPC, пользователя, PID и сети.
- Заголовки API пользовательского пространства Linux
- Для компиляции кода: GCC 6 (предпочтительно версия 7 или выше) или Clang 7 (или выше).
- Для автоматического создания заголовочных файлов: Clang Python Bindings.
- Питон 3.5 или новее
- Bazel версии 2.2.0 или CMake версии 3.12 или выше.
Использование Базеля
Bazel — рекомендуемая система сборки, с которой проще всего интегрироваться.
В нашей документации используется компилятор Clang. Если вам нужна конкретная цепочка инструментов (например, компилятор, компоновщик и т. д.), обратитесь к документации Bazel за информацией о том, как изменить цепочку инструментов компилятора по умолчанию.
Debian 10 (Бастер)
Чтобы установить зависимости сборки:
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
Генту
Требуемые параметры ядра:
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 (Бастер)
Чтобы установить зависимости сборки:
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
Генту
Требуемые параметры ядра:
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 ), вы увидите, что функция инструмента заключается в чтении данных из стандартного ввода и использовании функции deflate()
zlib для сжатия данных до тех пор, пока не будет прочитан маркер EOF
. Всего программа использует три функции из zlib:
-
deflateInit_()
: инициализировать сжатие. -
deflate()
: выполнить операцию сжатия фрагмента данных. -
deflateEnd()
: завершить сжатие и освободить динамически выделяемые структуры данных.
В реальном примере вы просмотрите библиотеку C/C++ и решите, какие функции необходимы. Возможная стратегия — начать с хост-кода и использовать библиотеку без изолированной программной среды. Затем, на втором этапе, вы можете создать изолированную библиотеку и адаптировать хост-код для использования изолированных вызовов функций.
2. Напишите правило сборки sapi_library.
После того как вы определили три функции zlib, необходимые из изолированной библиотеки zlib, вы можете определить правило сборки в файле BUILD . Документацию по правилу сборки sapi_library
можно найти на странице «Правила сборки» .
В приведенном ниже фрагменте кода показано определение sapi_library
для примера zlib SAPI. Используя атрибут lib
, Bazel получает указание найти в файле WORKSPACE библиотеку zlib.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
В результате создается изолированная библиотека zlib. Выходными данными является объект SAPI, который можно включить в хост-код и использовать для связи с изолированной библиотекой посредством вызовов RPC. Политика песочницы, используемая в этом примере, является политикой по умолчанию.
3. Напишите или измените код хоста
Пришло время включить сгенерированную библиотеку SAPI в хост-код.
Создайте песочницу
Используйте sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
для создания объекта песочницы.
Используйте sapi::zlib::ZlibApi api(&sandbox);
чтобы создать экземпляр объекта SAPI и, таким образом, сделать изолированные функции доступными для использования.
Используйте типы 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 .
Примеры
В разделе «Примеры» вы можете найти несколько библиотек, уже подготовленных командой SAPI.
,На этой странице вы узнаете, как создать собственную изолированную библиотеку C/C++ с помощью Sandboxed API (SAPI). Используйте его в качестве руководства вместе с примерами и документацией по коду в заголовочных файлах.
Создание зависимостей
В системе должны быть установлены следующие зависимости:
- Ядро Linux с поддержкой пространств имен UTS, IPC, пользователя, PID и сети.
- Заголовки API пользовательского пространства Linux
- Для компиляции кода: GCC 6 (предпочтительно версия 7 или выше) или Clang 7 (или выше).
- Для автоматического создания заголовочных файлов: Clang Python Bindings.
- Питон 3.5 или новее
- Bazel версии 2.2.0 или CMake версии 3.12 или выше.
Использование Базеля
Bazel — рекомендуемая система сборки, с которой проще всего интегрироваться.
В нашей документации используется компилятор Clang. Если вам нужна конкретная цепочка инструментов (например, компилятор, компоновщик и т. д.), обратитесь к документации Bazel за информацией о том, как изменить цепочку инструментов компилятора по умолчанию.
Debian 10 (Бастер)
Чтобы установить зависимости сборки:
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
Генту
Требуемые параметры ядра:
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 (Бастер)
Чтобы установить зависимости сборки:
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
Генту
Требуемые параметры ядра:
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 ), вы увидите, что функция инструмента заключается в чтении данных из стандартного ввода и использовании функции deflate()
zlib для сжатия данных до тех пор, пока не будет прочитан маркер EOF
. Всего программа использует три функции из zlib:
-
deflateInit_()
: инициализировать сжатие. -
deflate()
: выполнить операцию сжатия фрагмента данных. -
deflateEnd()
: завершить сжатие и освободить динамически выделяемые структуры данных.
В реальном примере вы просмотрите библиотеку C/C++ и решите, какие функции необходимы. Возможная стратегия — начать с хост-кода и использовать библиотеку без изолированной программной среды. Затем, на втором этапе, вы можете создать изолированную библиотеку и адаптировать хост-код для использования изолированных вызовов функций.
2. Напишите правило сборки sapi_library.
После того как вы определили три функции zlib, необходимые из изолированной библиотеки zlib, вы можете определить правило сборки в файле BUILD . Документацию по правилу сборки sapi_library
можно найти на странице «Правила сборки» .
В приведенном ниже фрагменте кода показано определение sapi_library
для примера zlib SAPI. Используя атрибут lib
, Bazel получает указание найти в файле WORKSPACE библиотеку zlib.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
В результате создается изолированная библиотека zlib. Выходными данными является объект SAPI, который можно включить в хост-код и использовать для связи с изолированной библиотекой посредством вызовов RPC. Политика песочницы, используемая в этом примере, является политикой по умолчанию.
3. Напишите или измените код хоста
Пришло время включить сгенерированную библиотеку SAPI в хост-код.
Создайте песочницу
Используйте sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
для создания объекта песочницы.
Используйте sapi::zlib::ZlibApi api(&sandbox);
чтобы создать экземпляр объекта SAPI и, таким образом, сделать изолированные функции доступными для использования.
Используйте типы 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 .
Примеры
В разделе «Примеры» вы можете найти несколько библиотек, уже подготовленных командой SAPI.