Sur cette page, vous allez apprendre à créer votre propre bibliothèque C/C++ en bac à sable avec l'API Sandboxed (SAPI). Utilisez-le comme guide en complément des exemples et de la documentation du code dans les fichiers d'en-tête.
Dépendances de compilation
Les dépendances suivantes doivent être installées sur le système :
- Noyau Linux compatible avec les espaces de noms UTS, IPC, utilisateur, PID et réseau
- En-têtes de l'API de l'espace utilisateur Linux
- Pour compiler votre code : GCC 6 (version 7 ou ultérieure recommandée) ou Clang 7 (ou version ultérieure)
- Pour générer automatiquement des fichiers d'en-tête : liaisons Python Clang
- Python 3.5 ou version ultérieure
- Bazel version 2.2.0 ou CMake version 3.12 ou ultérieure.
Utiliser Bazel
Bazel est le système de compilation recommandé et le plus facile à intégrer.
Notre documentation utilise le compilateur Clang. Si vous avez besoin d'une chaîne d'outils spécifique (par exemple, un compilateur, un éditeur de liens, etc.), consultez la documentation Bazel pour savoir comment modifier la chaîne d'outils du compilateur par défaut.
Debian 10 (Buster)
Pour installer les dépendances de compilation :
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
Options de noyau requises :
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Pour installer les dépendances de compilation :
emerge dev-util/bazel dev-python/typing dev-python/clang-python
Utiliser CMake
CMake est un système de métacompilation Open Source très répandu qui génère des fichiers de projet pour des outils de compilation tels que Ninja ou Make.
Debian 10 (Buster)
Pour installer les dépendances de compilation :
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
Options de noyau requises :
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Pour installer les dépendances de compilation :
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python
Processus de développement
Pour mettre en bac à sable une bibliothèque C/C++, vous devez préparer deux éléments pour votre projet :
- La bibliothèque dans un bac à sable
- Le code hôte qui utilisera la fonctionnalité exposée par votre bibliothèque sandboxée. SAPI générera automatiquement le stub RPC et l'objet SAPI pour vous lors du processus de compilation.
Vous connaissez peut-être zlib à partir des exemples Sandbox2. Ici, un programme entier (zpipe.c) a été mis en bac à sable. Dans les étapes suivantes, vous allez apprendre à utiliser SAPI pour sandboxer la bibliothèque zlib et utiliser la bibliothèque sandboxée.
1. Choisir les fonctions nécessaires
Si vous examinez le code hôte zlib (main_zlib.cc), vous pouvez constater que la fonctionnalité de l'outil consiste à lire les données à partir de stdin et à utiliser la fonction deflate()
de zlib pour compresser les données jusqu'à ce qu'un marqueur EOF
soit lu.
Au total, le programme utilise trois fonctions de zlib :
deflateInit_()
: pour initialiser la compressiondeflate()
: pour effectuer l'opération de compression sur le bloc de donnéesdeflateEnd()
: pour mettre fin à la compression et libérer les structures de données allouées dynamiquement
Dans un exemple concret, vous examinerez la bibliothèque C/C++ et déterminerez les fonctions nécessaires. Une stratégie possible consiste à commencer par le code hôte et à utiliser la bibliothèque non sandboxée. Ensuite, dans une deuxième étape, vous pouvez générer la bibliothèque bac à sable et adapter le code hôte pour utiliser les appels de fonction bac à sable.
2. Écrire la règle de compilation sapi_library
Une fois que vous avez identifié les trois fonctions zlib nécessaires à partir de la bibliothèque zlib en bac à sable, vous pouvez définir la règle de compilation dans le fichier BUILD. La documentation sur la règle de compilation sapi_library
est disponible sur la page Règles de compilation.
L'extrait de code ci-dessous montre la définition sapi_library
pour l'exemple SAPI zlib. À l'aide de l'attribut lib
, Bazel est invité à rechercher la bibliothèque zlib dans le fichier WORKSPACE.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
La bibliothèque zlib en bac à sable est alors générée. Le résultat est l'objet SAPI qui peut être inclus dans le code hôte et utilisé pour communiquer avec la bibliothèque en bac à sable via des appels RPC. La règle du bac à sable utilisée dans cet exemple est la règle par défaut.
3. Rédiger ou modifier le code organisateur
Il est maintenant temps d'intégrer la bibliothèque SAPI générée dans le code hôte.
Créer le bac à sable
Utilisez sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
pour créer un objet bac à sable.
Utilisez sapi::zlib::ZlibApi api(&sandbox);
pour instancier l'objet SAPI et rendre ainsi les fonctions en bac à sable disponibles.
Utiliser les types SAPI
Les types SAPI sont des types spéciaux sous la forme de classes C++ fournies par SAPI, car les types C standards ne fonctionnent pas toujours.
La première utilisation d'un type SAPI peut être observée dans la déclaration de strm
, où une structure SAPI est utilisée : sapi::v::Struct<sapi::zlib::z_stream> strm;
Le type de modèle (sapi::zlib::z_stream
) est un bon exemple de code généré automatiquement par la règle de compilation.
Pour en savoir plus, consultez la page Variables.
Effectuer des appels d'API
Pour appeler defalteInit_
, deflate
ou deflateEnd
, utilisez l'objet SAPI. Si vous décidez d'utiliser l'approche "change", vous devez vous assurer que les paramètres de la fonction correspondent aux valeurs attendues.
Exemple de chacun des appels dans l'exemple 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();
Utiliser les transactions SAPI
SAPI isole le code hôte de la bibliothèque en bac à sable et permet à l'appelant de redémarrer ou d'annuler les requêtes de traitement de données problématiques. SAPI Transaction va encore plus loin et répète automatiquement les processus ayant échoué.
Pour en savoir plus, consultez la page Transactions SAPI.
Exemples
Sous Exemples, vous trouverez quelques bibliothèques déjà préparées par l'équipe SAPI.