Auf dieser Seite erfahren Sie, wie Sie mit Sandboxed API (SAPI) Ihre eigene Sandbox-C/C++-Bibliothek erstellen. Verwenden Sie sie als Leitfaden zusammen mit den Beispielen und der Code-Dokumentation in den Header-Dateien.
Build-Abhängigkeiten
Die folgenden Abhängigkeiten müssen auf dem System installiert sein:
- Linux-Kernel mit Unterstützung für UTS-, IPC-, Nutzer-, PID- und Netzwerk-Namespaces
- Linux-Userspace-API-Header
- Zum Kompilieren des Codes: GCC 6 (Version 7 oder höher empfohlen) oder Clang 7 (oder höher)
- Zum automatischen Generieren von Header-Dateien: Clang Python-Bindungen
- Python 3.5 oder höher
- Bazel-Version 2.2.0 oder CMake- Version 3.12 oder höher.
Bazel verwenden
Bazel ist das empfohlene Build-System und lässt sich am einfachsten einbinden.
In unserer Dokumentation wird der Clang-Compiler verwendet. Wenn Sie eine bestimmte Toolchain (z.B. Compiler, Linker usw.) benötigen, finden Sie in der Bazel Dokumentation Informationen zum Ändern der Standard-Compiler-Toolchain.
Debian 10 (Buster)
So installieren Sie Build-Abhängigkeiten:
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
Erforderliche Kernel-Optionen:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
So installieren Sie Build-Abhängigkeiten:
emerge dev-util/bazel dev-python/typing dev-python/clang-pythonCMake verwenden
CMake ist ein beliebtes Open-Source-Meta-Build-System, das Projektdateien für Build-Tools wie Ninja oder Make generiert.
Debian 10 (Buster)
So installieren Sie Build-Abhängigkeiten:
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
Erforderliche Kernel-Optionen:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
So installieren Sie Build-Abhängigkeiten:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-pythonEntwicklungsprozess
Um eine C/C++-Bibliothek in einer Sandbox auszuführen, müssen Sie zwei Elemente für Ihr Projekt vorbereiten:
- Die Sandbox-Bibliothek
- Der Host-Code, der die von der Sandbox-Bibliothek bereitgestellte Funktionalität nutzt. SAPI generiert das SAPI-Objekt und den RPC Stub während des Build-Prozesses automatisch.
Möglicherweise kennen Sie die zlib-Bibliothek aus den Sandbox2 Beispielen hier wurde ein ganzes Programm (zpipe.c) in einer Sandbox ausgeführt. In den folgenden Schritten erfahren Sie, wie Sie mit SAPI die zlib-Bibliothek in einer Sandbox ausführen und die Sandbox-Bibliothek verwenden.
1. Entscheiden Sie, welche Funktionen benötigt werden
Wenn Sie sich den zlib-Host-Code
(main_zlib.cc),
sehen Sie, dass die Funktion des Tools darin besteht, Daten aus der Standardeingabe zu lesen und die
Funktion deflate() von zlib zu verwenden, um die Daten zu komprimieren, bis ein EOF Marker gelesen wird.
Insgesamt verwendet das Programm drei Funktionen aus zlib:
deflateInit_(): Zur Initialisierung für die Komprimierungdeflate(): Zum Ausführen des Komprimierungsvorgangs für den DatenblockdeflateEnd(): Zum Beenden der Komprimierung und Freigeben dynamisch zugewiesener Datenstrukturen
In einem realen Beispiel würden Sie die C/C++-Bibliothek überprüfen und entscheiden, welche Funktionen benötigt werden. Eine mögliche Strategie besteht darin, mit dem Host-Code zu beginnen und die Bibliothek ohne Sandbox zu verwenden. In einem zweiten Schritt könnten Sie dann die Sandbox-Bibliothek generieren und den Host-Code so anpassen, dass die Sandbox-Funktionsaufrufe verwendet werden.
2. Erstellen Sie die Build-Regel für die sapi_library
Nachdem Sie die drei zlib-Funktionen identifiziert haben, die aus der
Sandbox-zlib-Bibliothek benötigt werden, können Sie die Build-Regel in der
BUILD
Datei definieren. Die Dokumentation zur Build-Regel sapi_library finden Sie auf der
Seite Build-Regeln.
Das folgende Code-Snippet zeigt die Definition von sapi_library für das zlib-SAPI-Beispiel. Mit dem Attribut lib wird Bazel angewiesen, in der
WORKSPACE-Datei
nach der zlib-Bibliothek zu suchen.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
Das Ergebnis ist, dass die Sandbox-zlib-Bibliothek generiert wird. Die Ausgabe ist das SAPI-Objekt, das in den Host-Code aufgenommen und verwendet werden kann, um über RPC-Aufrufe mit der Sandbox-Bibliothek zu kommunizieren.
In diesem Beispiel wird die Standard-Sandbox-Konfiguration verwendet, die von
DefaultConfig
(sapi::SandboxConfig::DefaultConfig()) bereitgestellt wird.
3. Host-Code schreiben oder ändern
Jetzt ist es an der Zeit, die generierte SAPI-Bibliothek in den Host-Code einzubinden.
Sandbox erstellen
Verwenden Sie sapi::zlib::ZlibSandbox sandbox;, um ein Sandbox-Objekt zu erstellen.
Verwenden Sie sapi::zlib::ZlibApi api(&sandbox);, um das SAPI-Objekt zu instanziieren und so
die Sandbox-Funktionen zur Verwendung verfügbar zu machen.
Wenn Sie die Sandbox-Richtlinie, Flags, Umgebungsvariablen oder Limits anpassen möchten, beginnen Sie
mit sapi::SandboxConfig::DefaultConfig(), ändern Sie die entsprechenden Felder (mit
sapi::Sandbox2Config::DefaultPolicyBuilder(),
sapi::SandboxConfig::DefaultFlags() oder
sapi::SandboxConfig::DefaultEnvironmentVariables(), damit die Baseline-Einstellungen
beibehalten werden) und übergeben Sie sapi::SandboxConfig an den Sandbox-Konstruktor:
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-Typen verwenden
SAPI-Typen sind spezielle Typen in Form von C++-Klassen, die von SAPI bereitgestellt werden, da reguläre C-Typen manchmal nicht funktionieren.
Die erste Verwendung eines SAPI-Typs ist in der Deklaration von strm zu sehen, wo
ein SAPI-Struct verwendet wird: sapi::v::Struct<sapi::zlib::z_stream> strm;
Der Vorlagentyp (sapi::zlib::z_stream) ist ein gutes Beispiel für Code, der automatisch von der Build-Regel generiert wird.
Weitere Informationen finden Sie auf der Seite Variablen.
API-Aufrufe ausführen
Verwenden Sie das SAPI
Objekt, um Aufrufe an defalteInit_, deflate oder deflateEnd auszuführen. Wenn Sie sich für die Methode „Ändern“ entscheiden, müssen Sie darauf achten, dass die Funktionsparameter mit den erwarteten Werten übereinstimmen.
Ein Beispiel für jeden der Aufrufe im zlib Beispiel:
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-Transaktionen verwenden
SAPI isoliert den Host-Code von der Sandbox-Bibliothek und gibt dem Aufrufer die Möglichkeit, problematische Datenverarbeitungsanfragen neu zu starten oder abzubrechen. Die SAPI-Transaktion geht noch einen Schritt weiter und wiederholt fehlgeschlagene Prozesse automatisch.
Weitere Informationen finden Sie auf der Seite SAPI-Transaktionen.
Beispiele
Unter Beispiele finden Sie einige Bibliotheken, die bereits vom SAPI-Team vorbereitet wurden.