BoundsSanitizer

BoundsSanitizer(BoundSan)は、バイナリにインストゥルメンテーションを追加して、配列アクセスのまわりに境界チェックを挿入します。これらのチェックは、アクセスが安全であることをコンパイラがコンパイル時に証明できない場合と、配列のサイズが実行時にわかり、チェック可能である場合に追加されます。Android 10 は、Bluetooth とコーデックで BoundSan をデプロイします。BoundSan はコンパイラによって提供され、プラットフォーム全体のさまざまなコンポーネントで、デフォルトで有効になっています。

実装

BoundSan は、UBSan の境界サニタイザーを使用します。この緩和は、モジュール単位で有効になります。Android の重要なコンポーネントを安全に保護するものであり、無効にすることはできません。

追加のコンポーネントで BoundSan を有効にすることを強くおすすめします。権限を付与されたネイティブ コードまたは信頼できないユーザー入力を解析する複雑なネイティブ コードは、この機能を有効にするのに適しています。BoundSan の有効化に伴うパフォーマンス オーバーヘッドは、安全性を証明できない配列アクセスの数に依存します。平均的にオーバーヘッドの割合は小さいと予想し、パフォーマンスが問題になるかどうかをテストします。

ブループリント ファイルでの BoundSan の有効化

バイナリ モジュールとライブラリ モジュールの misc_undefined sanitize プロパティに "bounds" を追加することで、ブループリント ファイルで BoundSan を有効にできます。

sanitize: {
   misc_undefined: ["bounds"],
   diag: {
      misc_undefined: ["bounds"],
   },
   blacklist: "modulename_blacklist.txt",

diag

diag プロパティはサニタイザーの診断モードを有効にします。診断モードはテスト時にのみ使用します。診断モードではオーバーフローが発生してもプロセスが中止されず、緩和のセキュリティ上のメリットがなくなり、パフォーマンスのオーバーヘッドが高くなるため、製品版ビルドでは推奨されません。

blacklist

blacklist プロパティを使用すると、関数とソースファイルのサニタイズを回避するためにデベロッパーが使用できるブラックリスト ファイルを指定できます。パフォーマンスを重視し、対象のファイル / 関数が大きく影響する場合にのみ、このプロパティを使用します。これらのファイル / 関数を手動で監査して、配列アクセスが安全であることを確認します。詳細については、トラブルシューティングをご覧ください。

makefile での BoundSan の有効化

バイナリ モジュールとライブラリ モジュールの LOCAL_SANITIZE 変数に "bounds" を追加することで、makefile で BoundSan を有効にできます。

LOCAL_SANITIZE := bounds
# Optional features
LOCAL_SANITIZE_DIAG := bounds
LOCAL_SANITIZE_BLACKLIST := modulename_blacklist.txt

LOCAL_SANITIZE は、サニタイザーのカンマ区切りのリストを受け付けます。

LOCAL_SANITIZE_DIAG は診断モードをオンにします。診断モードはテスト時にのみ使用します。診断モードではオーバーフローが発生してもプロセスが中止されず、緩和のセキュリティ上のメリットがなくなり、パフォーマンスのオーバーヘッドが高くなるため、製品版ビルドでは推奨されません。

LOCAL_SANITIZE_BLACKLIST にはブラックリスト ファイルを指定できます。これにより、デベロッパーは関数とソースファイルのサニタイズを回避できます。パフォーマンスを重視し、対象のファイル / 関数が大きく影響する場合にのみ、このプロパティを使用します。これらのファイル / 関数を手動で監査して、配列アクセスが安全であることを確認します。詳細については、トラブルシューティングをご覧ください。

BoundSan の無効化

関数とソースファイルの BoundSan はブラックリストまたは関数属性で無効にできます。BoundSan を有効にしておくことが最善です。関数またはファイルが大量のパフォーマンス オーバーヘッドを引き起こしており、ソースを手動で確認した場合にのみ、BoundSan を無効にします。

関数属性ブラックリスト ファイル形式で BoundSan を無効にする方法については、Clang LLVM のドキュメントをご覧ください。他のサニタイザーに影響を与えないように、ターゲットのサニタイザーを指定するセクション名を使用して、ブラックリスト登録の範囲を特定のサニタイザーに限定する必要があります。

検証

BoundsSan 専用の CTS テストはありません。デバイスに影響しないことを確認するには、BoundSan の有効 / 無効にかかわらず CTS テストに合格するかどうかを検証します。

トラブルシューティング

BoundSan を有効にした後、コンポーネントを徹底的にテストして、以前に検出されなかった境界外のアクセスに対処していることを確認します。

BoundSan エラーには次の Tombstone 中止メッセージが含まれるため、簡単に特定できます。

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/foobar <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'ubsan: out-of-bounds'

診断モードで実行すると、ソースファイル、行番号、インデックス値が logcat に出力されます。デフォルトでは、このモードは中止メッセージをスローしません。logcat を調べて、エラーがないか確認します。

external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'