変数ガイド

はじめに

[概要] ページで説明したように、ホストコードはサンドボックス ライブラリに RPC 呼び出しを行います。サンドボックス化により、プロセス間でメモリが分離されるため、ホストコードはサンドボックス化されたライブラリのメモリに直接アクセスできません。

ホストコードがリモート プロセスの変数とメモリブロックにアクセスできるようにし、メインロジック コードの実装を簡素化するために、SAPI は包括的な C++ クラスのセットを提供します。ただし、多くの場合、ネイティブ C 型も使用できます。

特殊な型(SAPI 型)が必要になるのは、単純な型とメモリブロック(構造体、配列)へのポインタを渡す場合です。

たとえば、ポインタを受け取る関数を呼び出す場合、ポインタはサンドボックス ライブラリのメモリ内の対応するポインタに変換する必要があります。次のコード スニペットは、このシナリオを視覚化したものです。3 つの整数の配列ではなく、::sapi::v::Array<int> オブジェクトが作成され、サンドボックス化されたライブラリの API 呼び出しで渡すことができます。

int arr[3] = {1, 2, 3};
sapi::v::Array<int> sarr(arr, ABSL_ARRAYSIZE(arr));

利用可能なすべての SAPI タイプの包括的な概要については、SAPI プロジェクトのソースコードvar_*.h ヘッダー ファイルをご覧ください。これらのヘッダー ファイルは、さまざまな型のデータを表すクラスとテンプレートを提供します。例:

  • ::sapi::v::UChar は、よく知られている符号なし文字を表します。
  • ::sapi::v::Array<int> は整数の配列を表します。

SAPI のタイプ

このセクションでは、ホストコードでよく見られる 3 つの SAPI タイプを紹介します。

SAPI ポインタ

サンドボックス化される関数でポインタを渡す必要がある場合、このポインタは以下の PtrXXX() メソッドのいずれかから取得する必要があります。これらのメソッドは、SAPI 変数クラスによって実装されます。

ポインタ型
::PtrNone() サンドボックス化された API 関数に渡されたときに、ホストコード プロセスとサンドボックス化されたライブラリ プロセスの間で基盤となるメモリを同期しない。
::PtrBefore() サンドボックス化された API 関数呼び出しが行われるに、指しているオブジェクトのメモリを同期します。つまり、呼び出しが開始される前に、ポインタが指す変数のローカル メモリがサンドボックス ライブラリ プロセスに転送されます。
::PtrAfter() サンドボックス化された API 関数呼び出しのに、ポイント先のオブジェクトのメモリを同期します。つまり、ポインタが指す変数のリモート メモリは、呼び出しが完了したにホストコード プロセスのメモリに転送されます。
::PtrBoth() ::PtrBefore()::PtrAfter() の機能を組み合わせます。

SAPI ポインタのドキュメントはこちらで確認できます。

SAPI 構造体

テンプレート ::sapi::v::Structvar_struct.h で説明されています。既存の構造をラップするために使用できるコンストラクタを提供します。SAPI Struct は、SAPI ポインタで説明されているすべてのメソッドを提供し、サンドボックス化されたライブラリ呼び出しに使用できる ::sapi::v::Ptr オブジェクトを取得します。

次のコード スニペットは、構造が初期化され、zlib の例でサンドボックス化された関数呼び出しに渡される様子を示しています。

sapi::v::Struct<sapi::zlib::z_stream> strm;

if (ret = api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
                             version.PtrBefore(), sizeof(sapi::zlib::z_stream));

既存の構造体にポインタが含まれている場合、それらのポインタは Sandboxee のアドレスを指します。そのため、ホストコードからアクセスできるようになる前に、Sandboxee データを転送する必要があります。

SAPI 配列

テンプレート ::sapi::v::Arrayvar_array.h で説明されています。このテンプレートには 2 つのコンストラクタがあります。1 つは既存の要素配列をラップするために使用でき、もう 1 つは配列を動的に作成するために使用できます。

次のコード スニペット(sum の例から抜粋)は、このオブジェクトが所有していない配列をラップするコンストラクタの使用方法を示しています。

int arr[10];
sapi::v::Array<int> iarr(arr, ABSL_ARRAYSIZE(arr));

次のコード スニペットは、配列を動的に作成するために使用されるコンストラクタの例を示しています。

sapi::v::Array<uint8_t> buffer(PNG_IMAGE_SIZE(*image.mutable_data()));

SAPI Array は、SAPI ポインタで説明されているすべてのメソッドを提供し、サンドボックス化されたライブラリ呼び出しに使用できる ::sapi::v::Ptr オブジェクトを取得します。