ベンダー init

init プロセスにはほぼ無制限の権限が付与されており、システム パーティションとベンダー パーティションの両方からの入力スクリプトを使用して、ブートプロセス中にシステムを初期化します。このアクセスにより、Treble システム / ベンダー分割にセキュリティ ホールが生まれます。これは、ベンダーシステムとベンダー間のアプリケーション バイナリ インターフェース(ABI)の安定性が損なわれるようなファイルやプロパティなどへのアクセスを、ベンダー スクリプトが init に指示することがあるためです。

ベンダー init は、ベンダー固有の権限で /vendor にあるコマンドを実行する別個の security-enhanced Linux(SELinux)ドメイン vendor_init を使用することで、このセキュリティ ホールに対応するように設計されています。

メカニズム

ベンダー init はブートプロセスの初期段階において、SELinux コンテキスト u:r:vendor_init:s0 で init のサブプロセスをフォークします。この SELinux コンテキストの権限はデフォルトの init コンテキストの権限よりも大幅に少なく、ベンダー固有のファイルやプロパティへのアクセスか、システムとベンダー間の ABI の安定性が損なわれないアクセスに限定されています。

init は読み込むスクリプトをそれぞれチェックします。そのパスが /vendor で始まる場合、そのコマンドをベンダー init コンテキストで実行する必要があることを示すタグを付けます。組み込みの各 init には、コマンドをベンダー init サブプロセスで実行する必要があるかどうかを指定するブール値のアノテーションが付けられています。

  • ファイル システムにアクセスするほとんどのコマンドには、ベンダー init サブプロセスで実行する必要があることを示すアノテーションが付けられているため、ベンダー init SEPolicy の対象となります。
  • 内部の init 状態(サービスの開始や停止など)に影響するほとんどのコマンドは、通常の init プロセス内で実行されます。また、ベンダー スクリプトによって呼び出されていることを認識し、それぞれのコマンドの非 SELinux 権限で処理を行います。

init のメインの処理ループでは、ベンダー サブプロセスで実行する必要があることを示すアノテーションがコマンドに付けられていて、そのコマンドがベンダー スクリプトから発生しているかチェックされます。この条件が満たされる場合、コマンドがプロセス間通信(IPC)経由でベンダー init サブプロセスに送信され、そのベンダー init サブプロセスがコマンドを実行して結果を init に返します。

ベンダー init を使用する

ベンダー init はデフォルトで有効になっており、その制限は /vendor パーティション内にあるすべての init スクリプトに適用されます。ベンダー init は、スクリプトがシステム専用のファイルやプロパティなどに現在アクセスしていないベンダーに対して、透明性を維持する必要があります。

ただし、特定のベンダー スクリプト内のコマンドがベンダー init の制限に違反している場合、そのコマンドは失敗します。コマンドが失敗した場合、init からのカーネルログ(dmesg によって表示)に、失敗を示す行が記録されます。SELinux ポリシーが原因で失敗したコマンドについては、SELinux 監査が実行されます。SELinux 監査を含むエラーの例:

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

コマンドの失敗には、次の 2 通りの状況があります。

  • 意図的な制限のためにコマンドが失敗した場合(コマンドがシステム ファイルやシステム プロパティにアクセスした場合など)、Treble に対応した方法で、安定したインターフェースだけを使用するようにコマンドを再度実装する必要があります。Neverallow ルールにより、システムとベンダー間の ABI の安定性が損なわれるシステム ファイルへのアクセス権限は追加できません。
  • SELinux ラベルが新しく、まだシステム vendor_init.te で権限が付与されておらず、neverallow ルールによって権限が除外されていない場合には、デバイス固有の vendor_init.te で新しいラベルに権限が付与される場合があります。

Android 9 より前にリリースされたデバイスでは、デバイス固有の vendor_init.te ファイルに data_between_core_and_vendor_violators typeattribute を追加することで、neverallows ルールがバイパスされることがあります。

コードの場所

ベンダー init IPC 用のロジックの大半が system/core/init/subcontext.cpp にあります。

コマンドの表は system/core/init/builtins.cppBuiltinFunctionMap クラスにあります。これには、コマンドをベンダー init サブプロセスで実行する必要があるかどうかを示すアノテーションが含まれます。

ベンダー init の SEPolicy は、system/sepolicy でプライベート(system/sepolicy/private/vendor_init.te)ディレクトリとパブリック(system/sepolicy/public/vendor_init.te)ディレクトリの両方に格納されています。