HWAddressSanitizer

Hardware Assisted AddressSanitizer(HWASan)は AddressSanitizer(ASan)に似たメモリエラー検出ツールです。HWASan は ASan と比較して RAM の使用量がはるかに少ないため、システム全体のサニタイズに適しています。HWASan は Android 10 以上および AArch64 ハードウェアでのみ使用できます。ci.android.com からサポート対象の Pixel デバイスにビルド済みの HWASan イメージを書き込めます(詳細な設定手順)。

従来の ASan と比較した HWASan の特徴を次に示します。

  • CPU オーバーヘッドは同程度(~2 倍)
  • コードサイズ オーバーヘッドは同程度(40~50%)
  • RAM オーバーヘッドは大幅に少ない(10~35%)

HWASan は ASan と同じ種類のバグを検出します。

  • スタックとヒープのバッファ オーバーフロー / アンダーフロー
  • 解放後のヒープ使用
  • スコープ外のスタック使用
  • 二重解放 / ワイルド解放

さらに、HWASan は返却後のスタック使用を検出します。

実装の詳細と制限

HWASan はメモリのタグ付けアプローチに基づいており、小さなランダムタグ値がポインタとメモリアドレス範囲の両方に関連付けられます。メモリアクセスが有効になるには、ポインタとメモリタグが一致する必要があります。HWASan は ARMv8 の TBI(Top Byte Ignore)機能に依存します。この機能は仮想アドレスタグ付けとも呼ばれ、ポインタタグをアドレスの上位ビットに格納します。

詳細については、Clang のドキュメント サイトにある HWASan の設計をご覧ください。

設計上、HWASan には、オーバーフローを検出する ASan のサイズ制限レッドゾーンと、解放後の使用を検出する ASan の容量制限検疫機能はありません。したがって、HWASan は、オーバーフローの量がどれくらい大きいか、またはメモリがどれくらい前に割り当て解除されたかに関係なく、バグを検出できます。この点で HWASan には ASan よりも大きな利点があります。

ただし、HWASan では使用可能なタグ値が 256 個に制限されているため、プログラムの 1 回の実行でバグを見落とす確率が 0.4% あります。

HWASan は、システムコール引数でタグ付きポインタを受け入れる Linux カーネルを必要とします。サポートされているカーネルは、Android 10 以降のブランチと、AOSP カーネルソース リポジトリ内の該当するソースブランチで、Pixel 2、3、3a、4 の各デバイス向けに事前ビルドされたカーネルです。Pixel 2、3、3a、4 は、HWASan を使用してビルドされたシステム全体で動作することが実証されています。

Pixel 以外のデバイスについては、android-4.14 以降のブランチの共通 Android カーネルはサポートされていますが、Android 10 固有のブランチ(android-4.14-q など)はサポートされていません。 さらに、CL 1182220 の新しいツールチェーンと、CL 1164431 の対応するビルドシステムをチェリーピックすることにより、LLVM ツールチェーンを r370808 に更新する必要があります。

HWASan の使用

HWASan を使用してプラットフォーム全体をビルドするには、次のコマンドを実行します。

    lunch aosp_walleye-userdebug # (or any other product)
    make SANITIZE_TARGET=hwaddress
    

ASan と異なり、HWASan では 2 回のビルドは必要ありません。増分ビルドは正常に機能します。特別なフラッシュ命令またはワイプの要件はありません。静的な実行可能ファイルがサポートされます。libc 以外のすべてのライブラリのサニタイズはスキップしてかまいません。 また、ライブラリをサニタイズする場合、それにリンクされている実行可能ファイルもサニタイズする必要はありません。

モジュールのサニタイズをスキップするには、LOCAL_NOSANITIZE := hwaddress または sanitize: { hwaddress: false } を使用します。

スタック トレースの向上

HWASan は、フレーム ポインタに基づく高速なアンワインダーを使用して、プログラム内のすべてのメモリ割り当ておよび割り当て解除イベントのスタック トレースを記録します。Android ではデフォルトで AArch64 コードのフレーム ポインタが有効になるため、これは実際に効果的に機能します。マネージド コードをアンワインドする必要がある場合は、プロセス環境で HWASAN_OPTIONS=fast_unwind_on_malloc=0 を設定してください。不適切なメモリアクセスのスタック トレースでは、デフォルトでは「遅い」アンワインダーが使用されます。この設定は、割り当てトレースと割り当て解除トレースにのみ影響します。このオプションでは、負荷によっては CPU 使用率が非常に高くなります。

シンボル化

ASan ドキュメントのシンボル化をご覧ください。

アプリでの HWASan

AddressSanitizer と同様に、HWASan は Java コードを調べることはできませんが、JNI ライブラリ内のバグは検出できます。ASan と異なり、非 HWASan デバイスでの HWASan アプリの実行はサポートされていません

HWASan デバイスでは HWASan を使用してアプリをチェックできます。そのためには、Make で SANITIZE_TARGET:=hwaddress を指定するか、コンパイラ フラグで -fsanitize=hwaddress を指定して、アプリのコードをビルドします。