Pierwsze kroki z interfejsem Sandboxed API

Z tej strony dowiesz się, jak utworzyć własną bibliotekę C/C++ w piaskownicy za pomocą interfejsu Sandboxed API (SAPI). Korzystaj z niego jako przewodnika wraz z przykładami i dokumentacją kodu w plikach nagłówkowych.

Zależności kompilacji

W systemie muszą być zainstalowane te zależności:

  • Jądro systemu Linux z obsługą przestrzeni nazw UTS, IPC, użytkownika, PID i sieci
  • Nagłówki interfejsu API przestrzeni użytkownika systemu Linux
  • Do skompilowania kodu: GCC 6 (zalecana wersja 7 lub nowsza) lub Clang 7 (lub nowszy)
  • Do automatycznego generowania plików nagłówkowych: Clang Python Bindings
  • Python 3.5 lub nowszy
  • Bazel w wersji 2.2.0 lub CMake w wersji 3.12 lub nowszej.
    • Tylko CMake: GNU Make lub wersja nagłówków biblioteki libcap i narzędzie do kompilacji, np. Ninja (zalecane).

Korzystanie z Bazel

Bazel to zalecany system kompilacji, który najłatwiej zintegrować.

W naszej dokumentacji używamy kompilatora Clang. Jeśli potrzebujesz konkretnego łańcucha narzędzi (np. kompilatora, linkera itp.), zapoznaj się z dokumentacją Bazela, aby dowiedzieć się, jak zmienić domyślny łańcuch narzędzi kompilatora.

Debian 10 (Buster)

Aby zainstalować zależności kompilacji:

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

Wymagane opcje jądra:

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

Aby zainstalować zależności kompilacji:

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

Korzystanie z CMake

CMake to popularny system metakompilacji typu open source, który generuje pliki projektu dla narzędzi do kompilacji, takich jak Ninja czy Make.

Debian 10 (Buster)

Aby zainstalować zależności kompilacji:

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

Wymagane opcje jądra:

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

Aby zainstalować zależności kompilacji:

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

Proces programowania

Aby umieścić bibliotekę C/C++ w piaskownicy, musisz przygotować 2 elementy:

Możesz znać zlib z przykładów Sandbox2. W tym przypadku w piaskownicy umieszczono cały program (zpipe.c). Z poniższych kroków dowiesz się, jak używać interfejsu SAPI do testowania biblioteki zlib i korzystania z niej w środowisku testowym.

1. Określ, które funkcje są potrzebne.

Jeśli przyjrzysz się kodowi hosta zlib (main_zlib.cc), zobaczysz, że narzędzie odczytuje dane ze standardowego wejścia i używa funkcji deflate() zlib do kompresowania danych do momentu odczytania znacznika EOF. Program korzysta łącznie z 3 funkcji biblioteki zlib:

  • deflateInit_(): Inicjowanie kompresji
  • deflate(): aby przeprowadzić operację kompresji na bloku danych.
  • deflateEnd(): aby zakończyć kompresję i zwolnić dynamicznie przydzielone struktury danych.

W rzeczywistym przykładzie przejrzysz bibliotekę C/C++ i zdecydujesz, które funkcje są potrzebne. Możesz zacząć od kodu hosta i używać biblioteki bez piaskownicy. W drugim kroku możesz wygenerować bibliotekę w piaskownicy i dostosować kod hosta, aby używać wywołań funkcji w piaskownicy.

2. Napisz regułę kompilacji sapi_library

Po zidentyfikowaniu 3 funkcji zlib, które są potrzebne z biblioteki zlib w piaskownicy, możesz zdefiniować regułę kompilacji w pliku BUILD. Dokumentację reguły kompilacji sapi_library znajdziesz na stronie Reguły kompilacji.

Poniższy fragment kodu pokazuje definicję sapi_library dla przykładu SAPI zlib. Za pomocą atrybutu lib Bazel otrzymuje instrukcję, aby szukać biblioteki zlib w pliku WORKSPACE.

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

W rezultacie powstaje biblioteka zlib w piaskownicy. Wynikiem jest obiekt SAPI, który można uwzględnić w kodzie hosta i używać do komunikacji z biblioteką w piaskownicy za pomocą wywołań RPC. Zasady piaskownicy użyte w tym przykładzie to zasady domyślne.

3. Pisanie lub zmienianie kodu hosta

Teraz możesz włączyć wygenerowaną bibliotekę SAPI do kodu hosta.

Tworzenie piaskownicy

Użyj sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());, aby utworzyć obiekt w środowisku piaskownicy.

Użyj sapi::zlib::ZlibApi api(&sandbox);, aby utworzyć instancję obiektu SAPI, a tym samym udostępnić funkcje w piaskownicy do użycia.

Używanie typów SAPI

Typy SAPI to specjalne typy w postaci klas C++, które SAPI udostępnia, ponieważ czasami zwykłe typy C nie działają.

Pierwsze użycie typu SAPI można zaobserwować w deklaracji strm, gdzie używana jest struktura SAPI: sapi::v::Struct<sapi::zlib::z_stream> strm;

Typ szablonu (sapi::zlib::z_stream) to dobry przykład kodu wygenerowanego automatycznie przez regułę kompilacji.

Więcej informacji znajdziesz na stronie zmiennych.

Wywoływanie interfejsu API

Aby wykonywać połączenia na numery defalteInit_, deflate lub deflateEnd, użyj obiektu SAPI. Jeśli zdecydujesz się na użycie podejścia „change”, musisz się upewnić, że parametry funkcji odpowiadają oczekiwanym wartościom.

Przykład każdego wywołania w zlib example:

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

Korzystanie z transakcji SAPI

SAPI izoluje kod hosta od biblioteki w piaskownicy i umożliwia wywołującemu ponowne uruchomienie lub przerwanie problematycznych żądań przetwarzania danych. SAPI Transaction idzie o krok dalej i automatycznie powtarza procesy, które zakończyły się niepowodzeniem.

Więcej informacji znajdziesz na stronie transakcji SAPI.

Przykłady

W sekcji Przykłady znajdziesz kilka bibliotek przygotowanych przez zespół SAPI.