In questa pagina scoprirai come creare la tua libreria C/C++ in sandbox con l'API Sandboxed (SAPI). Usalo come guida insieme agli esempi e alla documentazione del codice nei file di intestazione.
Dipendenze build
Sul sistema devono essere installate le seguenti dipendenze:
- Kernel Linux con supporto per spazi dei nomi UTS, IPC, utente, PID e di rete
- Intestazioni API userspace Linux
- Per compilare il codice: GCC 6 (è preferibile la versione 7 o successive) o Clang 7 (o successive)
- Per la generazione automatica dei file di intestazione: Clang Python Bindings
- Python 3.5 o versioni successive
- Bazel versione 2.2.0 o CMake versione 3.12 o successive.
Utilizzo di Bazel
Bazel è il sistema di compilazione consigliato ed è il più semplice da integrare.
La nostra documentazione utilizza il compilatore Clang. Se hai bisogno di una toolchain specifica (ad es. compilatore, linker e così via), consulta la documentazione di Bazel per informazioni su come modificare la toolchain del compilatore predefinita.
Debian 10 (Buster)
Per installare le dipendenze di compilazione:
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
Opzioni del kernel richieste:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Per installare le dipendenze di compilazione:
emerge dev-util/bazel dev-python/typing dev-python/clang-python
Utilizzo di CMake
CMake è un popolare sistema di meta-build open source che genera file di progetto per strumenti di build come Ninja o Make.
Debian 10 (Buster)
Per installare le dipendenze di compilazione:
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
Opzioni del kernel richieste:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Per installare le dipendenze di compilazione:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python
Processo di sviluppo
Per eseguire il sandboxing di una libreria C/C++, devi preparare due elementi per il tuo progetto:
- La libreria in sandbox
- Il codice host che utilizzerà la funzionalità esposta dalla libreria in sandbox. SAPI genererà automaticamente l'oggetto SAPI e lo stub RPC durante il processo di compilazione.
Potresti avere familiarità con zlib degli esempi di Sandbox2. Qui è stato sottoposto a sandbox un intero programma (zpipe.c). Nei passaggi seguenti, imparerai a utilizzare SAPI per inserire la libreria zlib in un ambiente sandbox e utilizzare la libreria sandbox.
1. Decidere quali funzioni sono necessarie
Se esamini il codice host zlib
(main_zlib.cc),
puoi notare che la funzionalità dello strumento consiste nel leggere i dati da stdin e utilizzare
la funzione deflate()
di zlib per comprimere i dati fino alla lettura di un marcatore EOF
.
In totale, il programma utilizza tre funzioni di zlib:
deflateInit_()
: Per l'inizializzazione per la compressionedeflate()
: Per eseguire l'operazione di compressione sul blocco di datideflateEnd()
: per terminare la compressione e liberare le strutture di dati allocate dinamicamente
In un esempio reale, esamineresti la libreria C/C++ e decideresti quali funzioni sono necessarie. Una possibile strategia è iniziare con il codice host e utilizzare la libreria senza sandbox. Poi, in un secondo passaggio, potresti generare la libreria sandbox e adattare il codice host per utilizzare le chiamate di funzione sandbox.
2. Scrivi la regola di compilazione sapi_library
Dopo aver identificato le tre funzioni zlib necessarie dalla libreria zlib in sandbox, puoi definire la regola di compilazione nel file BUILD. La documentazione per la regola di compilazione sapi_library
è disponibile nella pagina
Regole di compilazione.
Lo snippet di codice riportato di seguito mostra la definizione di sapi_library
per l'esempio di SAPI zlib. Utilizzando l'attributo lib
, viene indicato a Bazel di cercare la libreria zlib nel file
WORKSPACE.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
Il risultato è la generazione della libreria zlib in sandbox. L'output è l'oggetto SAPI che può essere incluso nel codice host e utilizzato per comunicare con la libreria in sandbox tramite chiamate RPC. Il criterio sandbox utilizzato in questo esempio è il criterio predefinito.
3. Scrivere o modificare il codice host
Ora è il momento di incorporare la libreria SAPI generata nel codice host.
Crea la sandbox
Utilizza sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
per creare un oggetto sandbox.
Utilizza sapi::zlib::ZlibApi api(&sandbox);
per creare un'istanza dell'oggetto SAPI e quindi
rendere disponibili le funzioni in sandbox.
Utilizzare i tipi SAPI
I tipi SAPI sono tipi speciali sotto forma di classi C++ che SAPI fornisce perché a volte i tipi C regolari non funzionano.
Il primo utilizzo di un tipo SAPI può essere osservato nella dichiarazione di strm
, dove
viene utilizzata una struttura SAPI: sapi::v::Struct<sapi::zlib::z_stream> strm;
Il tipo di modello (sapi::zlib::z_stream
) è un buon esempio di codice
generato automaticamente dalla regola di compilazione.
Per ulteriori dettagli, consulta la pagina Variabili.
Effettuare chiamate API
Per effettuare chiamate a defalteInit_
, deflate
o deflateEnd
, utilizza l'oggetto SAPI. Se decidi di utilizzare l'approccio "modifica", devi assicurarti che
i parametri della funzione corrispondano ai valori previsti.
Un esempio di ciascuna delle chiamate nell'esempio 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();
Utilizzo delle transazioni SAPI
SAPI isola il codice host dalla libreria in sandbox e consente al chiamante di riavviare o interrompere le richieste di elaborazione dei dati problematiche. SAPI Transaction va oltre e ripete automaticamente i processi non riusciti.
Per maggiori dettagli, consulta la pagina Transazioni SAPI.
Esempi
Nella sezione Esempi puoi trovare alcune librerie già preparate dal team SAPI.