Android における Security-Enhanced Linux

Android では、Android セキュリティ モデルの一環として、Security-Enhanced Linux(SELinux)を使用して、root / スーパーユーザー権限(Linux 機能)で実行されているプロセスを含むすべてのプロセスに、強制アクセス制御(MAC)を適用しています。Android の SELinux 実装には、多くの企業と組織が貢献しています。Android では、SELinux を使用することで、システム サービスの効果的な保護・制限、アプリケーション データとシステムログへのアクセスの制御、悪意のあるソフトウェアの影響の軽減を実現し、モバイル デバイスのコードにおける潜在的な欠陥からユーザーを保護しています。

SELinux は、拒否をデフォルトとする原則で動作します。つまり、明示的に許可されていないものはすべて拒否されます。SELinux は、次の 2 つのグローバル モードで動作します。

  • permissive モード: 権限の拒否はログに記録されますが適用されません。
  • enforcing モード: 権限の拒否がログに記録され、適用されます

Android には enforcing モードの SELinux と、対応するセキュリティ ポリシーが含まれています。このポリシーはデフォルトで AOSP 全体に適用されます。enforcing モードでは、許可されていない操作はブロックされ、試行された違反はカーネルによってすべて dmesglogcat に記録されます。開発時には、記録されたエラーに基づいて、ソフトウェアと SELinux ポリシーを改善してから適用する必要があります。詳細については、SELinux の実装をご覧ください。

SELinux では、ドメイン単位の permissive モードもサポートされています。このモードでは、特定のドメイン(プロセス)を permissive モードにして、システムのその他のドメインをグローバルに enforcing モードにできます。ドメインとは、セキュリティ ポリシーで単一または一連のプロセスを識別するためのラベルです。同じドメインによってラベル付けされたプロセスは、セキュリティ ポリシーですべて同一に扱われます。ドメイン単位の permissive モードでは、システムの追加部分や、新しいサービスの導入に伴って開発するポリシーに、(システムの残りの部分を enforcing モードにしたまま)SELinux を徐々に適用していくことができます。

背景

Android セキュリティ モデルの一部は、アプリ サンドボックスのコンセプトがベースになっています。各アプリケーションはそれぞれのサンドボックスで実行されます。Android 4.3 より前まで、これらのサンドボックスは、各アプリのインストール時に一意の Linux UID を作成することで定義されていました。 Android 4.3 以降では SELinux を使用して、Android アプリ サンドボックスの境界を定義します。

Android 5.0 以降では、Android 4.3 の permissive モードのリリースと、Android 4.4 の部分的な enforcing モードの実装を基礎として、SELinux が完全に実装されています。 Android ではこの変更により、限定された重要なドメイン(installdnetdvoldzygote)ではなく、60 を超えるすべてのドメインに enforcing モードを適用する方法に移行しました。詳細は以下のとおりです。

  • Android 5.x 以降では、すべてが enforcing モードで実行されます。
  • init 以外のプロセスは init ドメインで実行することはできません。
  • block_devicesocket_devicedefault_service に対する一般的な拒否は、デバイスが特別なドメインを必要とすることを示しています。

Android 6.0 では、ポリシーの許容性を低減させ、ユーザー間の適切な分離、IOCTL フィルタリング、公開サービスの脅威の低減、SELinux ドメインの厳格化、/proc アクセスの大幅な制限などを図ることで、システムが強化されました。

Android 7.0 では SELinux 構成を更新して、アプリケーション サンドボックスのロックダウンを強化し、攻撃対象領域を狭めています。またこのリリースでは、モノリシックなメディアサーバー スタックを小さなプロセスに分割して、権限の範囲を縮小させています。詳しくは、Linux カーネルの防御の強化による Android の保護、およびメディア スタックの強化をご覧ください。

Android 8.0 では Treble と連携するように SELinux が更新され、低レベルのベンダーコードが Android システム フレームワークから分離されました。このリリースでは SELinux ポリシーが更新され、デバイス メーカーと SOC ベンダーがポリシーの独自の部分を更新し、イメージ(vendor.imgboot.img など)を作成して、それらのイメージをプラットフォームから独立して更新できるようになりました(プラットフォームをイメージと独立して更新することも可能)。

ベンダー イメージよりも新しい(バージョンが大きい)プラットフォーム(フレームワーク)をデバイスで実行することはできますが、その逆はできません。つまり、プラットフォーム(system.img)のバージョンよりも新しいベンダー イメージ(vendor.img/odm.img)のバージョンを使用することはできません。そのため、ベンダー イメージのバージョンを更新すると、プラットフォーム SELinux ポリシーのバージョンがポリシーのベンダー SELinux 部分よりも古くなり、SELinux の互換性の問題が発生する可能性があります。Android 8.0 モデルには、互換性を保持し、不要な同時 OTA を防止するための方法が用意されています。

参考情報

有益な SELinux ポリシーを構築する方法については、次のリソースをご覧ください。SELinux のコンセプトの一部は Android では使用されません。外部ドキュメントを検討する際には、特異性のセクションをご覧ください。