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 ポリシーを構築する方法については、次のリソースをご覧ください。