SELinux のコンセプト

SELinux のコンセプトについて知識を深めるには、このページをご覧ください。

強制アクセス制御

Security Enhanced Linux(SELinux)は、Linux オペレーティング システム用の強制アクセス制御(MAC)システムです。MAC システムは、Linux で一般的な任意アクセス制御(DAC)システムとは異なります。DAC システムにはオーナーシップのコンセプトがあり、特定のリソースのオーナーが、そのリソースに関連するアクセス権限を制御します。DAC システムでは一般的に制御が緩いため、意図しない権限昇格が発生しやすくなります。一方 MAC システムでは、すべてのアクセス試行に関する決定を中核となる制御システムが行います。

SELinux は Linux セキュリティ モジュール(LSM)フレームワークの一部として実装されており、さまざまなカーネル オブジェクトと、それに対するセキュリティ上重要なアクションを認識します。これら各アクションが実行される時点で LSM フック関数が呼び出され、不透明なセキュリティ オブジェクトに保存されている情報に基づいて、アクションを許可するかどうかが判断されます。SELinux では、これらのフックの実装とセキュリティ オブジェクトの管理を行い、それらを独自のポリシーと組み合わせて、アクセスの判断を決定します。

Android のアクセス制御ポリシーは、Android の他のセキュリティ対策と組み合わせて使用することで、マシンやアカウントの侵害による潜在的な損害を大幅に低下させます。Android の任意アクセス制御や強制アクセス制御などのツールを使用することで、ソフトウェアを確実に最小の権限レベルで実行するための構造が実現します。これによって、攻撃の影響が緩和され、データの上書きや送信を行う異常なプロセスが発生する可能性が低下します。

Android 4.3 以降では、従来の任意アクセス制御(DAC)環境に加えて、SELinux による強制アクセス制御(MAC)が導入されています。たとえば、raw ブロック デバイスに書き込むには、通常、ソフトウェアを root ユーザー アカウントとして実行する必要があります。従来型の DAC ベースの Linux 環境では、root ユーザーが侵害されると、そのユーザーがすべての raw ブロック デバイスに書き込めるようになります。しかし SELinux を使用すると、こうしたデバイスにラベルを付けることで、root 権限が割り当てられたプロセスが書き込めるデバイスを、関連するポリシーで指定されたデバイスに限定できます。これにより、そのプロセスが特定の raw ブロック デバイス以外のデータとシステム設定を上書きできなくなります。

その他の脅威の例と、SELinux を使用してそれらに対応する方法については、ユースケースをご覧ください。

適用レベル

SELinux はさまざまなモードで実装できます。

  • Permissive - SELinux セキュリティ ポリシーが適用されず、ログへの記録のみが行われます。
  • Enforcing - セキュリティ ポリシーが適用され、ログに記録されます。エラーは EPERM エラーとして示されます。

どちらか 1 つのモードを選択することで、ポリシーによって対処するか、潜在的なエラーの収集を可能にするだけにするかを決定できます。Permissive は特に実装時に役立ちます。

タイプ、属性、ルール

Android は、ポリシーに関して SELinux の Type Enforcement(TE)コンポーネントに依存しています。つまり、すべてのオブジェクト(ファイル、プロセス、ソケットなど)に、それぞれタイプが関連付けられています。たとえば、デフォルトでは、アプリのタイプは untrusted_app に設定されます。プロセスのタイプはドメインとも呼ばれます。タイプには 1 つまたは多数の属性を持つアノテーションを付与できます。属性は、複数のタイプを同時に参照する場合に有効です。

オブジェクトはクラス(ファイル、ディレクトリ、シンボリック リンク、ソケットなど)にマッピングされ、クラスごとに異なるアクセス権の種類が権限で表されます。たとえば、クラス fileopen 権限が存在する場合が考えられます。タイプと属性は Android SELinux ポリシーの一部として定期的に更新されますが、権限とクラスは静的に定義され、新しい Linux リリースの一部として更新されることはあまりありません。

ポリシールールallow source target:class permissions; の形式を取ります。

  • Source - ルールの対象の種類(または属性)。アクセスのリクエスト元。
  • Target - オブジェクトのタイプ(または属性)。アクセスのリクエスト先。
  • Class - アクセス対象のオブジェクトの種類(ファイル、ソケットなど)。
  • Permissions - 実行される操作(または一連の操作)(読み取り、書き込みなど)。

ルールの例を次に示します。

allow untrusted_app app_data_file:file { read write };

この例は、app_data_file とラベル付けされているファイルの読み取りと書き込みがアプリに許可されていることを示しています。アプリには他にもタイプが存在します。たとえば、isolated_app は、マニフェストに isolatedProcess=true が含まれるアプリサービスに使用されます。両方のタイプについてルールを繰り返す代わりに、Android は、アプリを対象とするすべてのタイプに appdomain という名前の属性を使用します。

# Associate the attribute appdomain with the type untrusted_app.
typeattribute untrusted_app appdomain;

# Associate the attribute appdomain with the type isolated_app.
typeattribute isolated_app appdomain;

allow appdomain app_data_file:file { read write };

属性名を指定するルールを記述すると、その属性に関連付けられているドメインまたはタイプのリストに、指定した名前が自動的に拡張されます。主な属性としては、次の属性が挙げられます。

  • domain - すべてのプロセスタイプに関連付けられている属性。
  • file_type - すべてのファイル形式に関連付けられている属性。

マクロ

特にファイルへのアクセスに関しては、考慮すべき多くの種類の権限が存在します。たとえば、ファイルを開く、またはファイルに対して stat を呼び出す場合、read 権限では不十分です。ルールの定義を簡略化するために、Android には、最も一般的なケースを処理するための一連のマクロが用意されています。たとえば、open などの不足している権限を追加するには、上に示したルールを次のように書き換えます。

allow appdomain app_data_file:file rw_file_perms;

その他の有用なマクロの例については、global_macros ファイルと te_macros ファイルをご覧ください。関連する権限の拒否による失敗の可能性を低減するには、可能な限りマクロを使用する必要があります。

タイプを定義したら、タイプが表すファイルまたはプロセスに関連付ける必要があります。この関連付けを行う方法について詳しくは、SELinux の実装をご覧ください。ルールの詳細については、SELinux Notebook をご覧ください。

セキュリティ コンテキストとカテゴリ

SELinux ポリシーをデバッグする、またはファイルにラベルを付与する(file_contexts を使用して、または ls -Z の実行時に)場合は、セキュリティ コンテキストラベルとも呼ばれます)に出くわす可能性があります。これを、u:r:untrusted_app:s0:c15,c256,c513,c768 を例に挙げて説明します。セキュリティ コンテキストの形式は user:role:type:sensitivity[:categories] です。通常、コンテキストの userrolesensitivity の各フィールドは無視できます(特異性を参照)。type フィールドについては、前のセクションで説明しています。categories は、SELinux のマルチレベル セキュリティ(MLS)サポートの一部です。Android 12 以降、カテゴリは次の目的で使用されます。

  • アプリデータを別のアプリによるアクセスから分離する
  • アプリデータを、ある物理ユーザーから別の物理ユーザーに分離する。

特異性

Android は SELinux に用意されている機能をすべて使用するわけではありません。外部ドキュメントをお読みになる際は、次の点に留意してください。

  • AOSP のポリシーの大部分は、カーネル ポリシー言語を使用して定義されています。Common Intermediate Language(CIL)の使用については、いくつかの例外が存在します。
  • SELinux のユーザーは使用されません。定義されているユーザーは u のみです。必要に応じて、実際のユーザーはセキュリティ コンテキストのカテゴリ フィールドを使用して表されます。
  • SELinux のロールとロールベース アクセス制御(RBAC)は使用されません。デフォルトの 2 つのロールが定義されて、使用されます(サブジェクトの場合は r、オブジェクトの場合は object_r)。
  • SELinux の感度は使用されません。デフォルトの s0 感度が常に設定されています。
  • SELinux のブール値は使用されません。デバイスに対してポリシーが作成されると、そのポリシーはデバイスの状態に依存しません。これにより、ポリシーの監査とデバッグが簡略化されます。