このページでは、SELinux ポリシーをビルドする方法を説明します。SELinux ポリシーは、コア AOSP ポリシー(プラットフォーム)とデバイス固有のポリシー(ベンダー)を組み合わせてビルドされます。Android 4.4 から Android 7.0 までの SELinux ポリシーのビルドフローでは、sepolicy のすべてのフラグメントをマージし、ルート ディレクトリにモノリシックなファイルを生成していました。そのため、SoC ベンダーと ODM メーカーは、ポリシーが変更されるたびに、boot.img
(非 A/B デバイスの場合)または system.img
(A/B デバイスの場合)を変更していました。
Android 8.0 以降では、プラットフォーム ポリシーとベンダー ポリシーは別々にビルドされます。SOC と OEM は、各自が担当するポリシーの部分を更新し、各自のイメージ(vendor.img
や boot.img
)をビルドした後、プラットフォームの更新と無関係にそれらのイメージを更新できます。
ただし、モジュール化された SELinux ポリシー ファイルは /vendor
パーティションに保存されるため、init
プロセスは早めにシステム パーティションとベンダー パーティションをマウントする必要があります。これは、それらのパーティションから SELinux ファイルを読み取り、システム ディレクトリのコア SELinux ファイルがカーネルに読み込まれる前にこのファイルとマージできるようにするためです。
ソースファイル
SELinux をビルドするためのロジックは、次のファイルにあります。
external/selinux
: HOST コマンドライン ユーティリティをビルドし、SELinux ポリシーと SELinux ラベルをコンパイルするために使用する、外部 SELinux プロジェクト。external/selinux/libselinux
: Android は、外部libselinux
プロジェクトのサブセットのみを、Android 固有のカスタマイズとともに使用します。詳細については、external/selinux/README.android
をご覧ください。-
external/selinux/libsepol
: external/selinux/checkpolicy
: SELinux ポリシー コンパイラ(ホスト実行可能:checkpolicy
、checkmodule
、dispol
)。libsepol
に依存します。
system/sepolicy
: コンテキスト ファイルとポリシー ファイルを含む、コアの Android SELinux ポリシー構成。主な sepolicy ビルドロジックもこれに含まれています(system/sepolicy/Android.mk
)。
system/sepolicy
内のファイルについて詳しくは、SELinux の実装をご覧ください。
Android 7.x 以前
このセクションでは、Android 7.x 以前で SELinux ポリシーがどのようにビルドされているかを説明します。
Android 7.x 以前のビルドプロセス
SELinux ポリシーは、コア AOSP ポリシーとデバイス固有のカスタマイズを組み合わせて作成されています。組み合わせたポリシーは、ポリシー コンパイラと各種のチェッカーに渡されます。デバイス固有のカスタマイズは、デバイス固有の Boardconfig.mk
ファイルで定義される BOARD_SEPOLICY_DIRS
変数によって行われます。このグローバルなビルド変数には、追加のポリシー ファイルを検索する順序を指定するディレクトリのリストが含まれています。
たとえば、SoC ベンダーと ODM は、それぞれに SoC 固有の設定用、デバイス固有の設定用のディレクトリを追加する場合があります。その場合、そのデバイスに生成される最終的な SELinux 構成は次のようになります。
BOARD_SEPOLICY_DIRS += device/SOC/common/sepolicy
BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy
system/sepolicy
と BOARD_SEPOLICY_DIRS
の file_contexts ファイルのコンテンツを連結して、デバイスに file_contexts.bin
が生成されます。
sepolicy
ファイルは、複数のソースファイルで構成されています。
- 書式なしテキスト
policy.conf
は、security_classes
、initial_sids
、*.te
ファイル、genfs_contexts
、port_contexts
をこの順序で連結することで生成されます。 - 各ファイル(
security_classes
など)のコンテンツは、system/sepolicy/
とBOARDS_SEPOLICY_DIRS
の名前が同じファイルを連結したものです。 policy.conf
は SELinux コンパイラに送信されて構文チェックが行われ、デバイスにsepolicy
としてバイナリ形式でコンパイルされます。
SELinux ファイル
コンパイル後、7.x 以前を実行する Android デバイスには、一般的に次の SELinux 関連ファイルが含まれることになります。
selinux_version
- sepolicy: ポリシー ファイル(
security_classes
、initial_sids
、*.te
など)を組み合わせた後のバイナリ出力 file_contexts
property_contexts
seapp_contexts
service_contexts
system/etc/mac_permissions.xml
詳しくは、SELinux の実装をご覧ください。
SELinux の初期化
システムが起動したときに、SELinux は permissive モード(enforcing モードではなく)になっています。init プロセスが次のタスクを実行します。
/sys/fs/selinux/load
を通じて ramdisk からカーネルにsepolicy
ファイルを読み込みます。- SELinux を enforcing モードに切り替えます。
re-exec()
を実行して、それ自体に SELinux ドメインルールを適用します。
起動時間を短縮するには、init
プロセスでできるだけ早く re-exec()
を実行します。
Android 8.0 以上
Android 8.0 では、互換性を維持しながら、プラットフォーム ポリシーとベンダー ポリシーを独立して更新できるようにするため、SELinux ポリシーはプラットフォーム コンポーネントとベンダー コンポーネントに分割されます。
さらにプラットフォームの sepolicy は、ベンダー ポリシーのライターに対し特定のタイプと属性をエクスポートするために、プラットフォーム プライベート ポリシーと、プラットフォーム パブリック ポリシーに分割されます。プラットフォーム パブリックのタイプと属性は、対応するプラットフォーム バージョンの安定した API として維持されることが保証されます。以前のプラットフォームのパブリック タイプまたは属性との互換性は、プラットフォーム マッピング ファイルを使用することで、複数のバージョンについて保証されます。
Android 8.0 のビルドプロセス
Android 8.0 の SELinux ポリシーは、/system
と /vendor
からの部分を組み合わせることで作成されます。これを適切に設定するためのロジックは、/platform/system/sepolicy/Android.mk
にあります。
ポリシーは次の場所に存在します。
場所 | 内容 |
---|---|
system/sepolicy/public |
プラットフォームの sepolicy API |
system/sepolicy/private |
プラットフォーム実装の詳細(ベンダーは無視することが可能) |
system/sepolicy/vendor |
ベンダーが使用できるポリシー ファイルとコンテキスト ファイル(必要な場合、ベンダーは無視することが可能) |
BOARD_SEPOLICY_DIRS |
ベンダーの sepolicy |
BOARD_ODM_SEPOLICY_DIRS (Android 9 以上) |
ODM の sepolicy |
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 以上) |
system_ext の sepolicy API |
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 以上) |
system_ext 実装の詳細(ベンダーは無視することが可能) |
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 以上) |
product の sepolicy API |
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 以上) |
product 実装の詳細(ベンダーは無視することが可能) |
ビルドシステムは、このポリシーを取得して、system、system_ext、product、vendor、odm ポリシーの各コンポーネントを、対応するパーティションに生成します。手順は次のとおりです。
- ポリシーを次のように SELinux Common Intermediate Language(CIL)形式に変換します。
- パブリック プラットフォーム ポリシー(system + system_ext + product)
- プライベート + パブリック ポリシーの組み合わせ
- パブリック + ベンダーおよび
BOARD_SEPOLICY_DIRS
ポリシー
- ベンダー ポリシーの一部としてパブリックから提供されたポリシーのバージョニングを行います。
これは、作成されたパブリック CIL ポリシーを使用して、パブリック + ベンダー +
BOARD_SEPOLICY_DIRS
ポリシーの組み合わせについて、プラットフォーム ポリシーにリンクされる属性に変換する必要がある部分を通知することによって行われます。 - プラットフォーム部分とベンダー部分をリンクするマッピング ファイルを作成します。 最初の段階では、パブリック ポリシーからのタイプが、ベンダー ポリシー内の対応する属性にリンクされるだけです。その後、これは将来のプラットフォーム バージョンで維持されるファイルの基盤となり、このプラットフォーム バージョンを対象とするベンダー ポリシーとの互換性が確保されます。
- ポリシー ファイル(デバイス上とプリコンパイルされたソリューションの両方で作成される)を組み合わせます。
- マッピング、プラットフォーム、ベンダーのポリシーを組み合わせます。
- 出力バイナリ ポリシー ファイルをコンパイルします。
プラットフォーム パブリック sepolicy
プラットフォーム パブリック sepolicy には、system/sepolicy/public
で定義されているものすべてが含まれています。プラットフォームは、パブリック ポリシーで定義されているタイプと属性が、そのプラットフォーム バージョンの安定した API であると想定できます。これにより、プラットフォームからエクスポートされた sepolicy の一部が形成されます。このプラットフォームには、ベンダー(デバイス)ポリシーのデベロッパーがデバイス固有のポリシーを追加で書き込む可能性があります。
それぞれのタイプは、PLATFORM_SEPOLICY_VERSION
ビルド変数で定義され、ベンダー ファイルの基準になっているポリシーのバージョンに応じてバージョニングされます。バージョニングされたパブリック ポリシーは、ベンダー ポリシーとプラットフォーム ポリシー(元の形式で)に含まれます。したがって最終的なポリシーには、プライベート プラットフォーム ポリシー、現在のプラットフォームのパブリック sepolicy、デバイス固有のポリシー、デバイス ポリシーの基準になったプラットフォーム バージョンに対してバージョニングされたパブリック ポリシーが含まれます。
プラットフォーム プライベート sepolicy
プラットフォーム プライベート sepolicy には、/system/sepolicy/private
で定義されたものがすべて含まれます。ポリシーのこの部分は、プラットフォームが機能するために必要な、プラットフォーム固有のタイプ、権限、属性を形成します。これらは vendor/device
ポリシーのライターにはエクスポートされません。プラットフォーム以外のポリシー ライターは、プラットフォーム プライベート sepolicy で定義されたタイプ、属性、ルールに基づいてポリシー拡張を作成してはなりません。さらにこれらのルールは、フレームワークのみの更新で変更することが可能であり、削除される場合もあります。
プラットフォーム プライベート マッピング
プラットフォーム プライベート マッピングには、以前のプラットフォーム バージョンのプラットフォーム パブリック ポリシーで公開された属性を、現在のプラットフォーム パブリック sepolicy で使用されているコンクリート タイプにマッピングするポリシー ステートメントが含まれています。それにより、以前のプラットフォーム パブリック sepolicy バージョンのプラットフォーム パブリック属性に基づいて作成されたベンダー ポリシーが、機能を継続できるようになります。バージョニングは、そのプラットフォーム バージョンの AOSP で設定されている PLATFORM_SEPOLICY_VERSION
ビルド変数に基づきます。このプラットフォームがベンダー ポリシーを受け取ることが予期される、すべての前プラットフォーム バージョンのそれぞれに、別個のマッピング ファイルが存在します。詳しくは、互換性をご覧ください。
Android 11 以上
system_ext と product の sepolicy
Android 11 では、system_ext ポリシーと product ポリシーが追加されました。プラットフォームの sepolicy と同様に、system_ext ポリシーと product ポリシーは、パブリック ポリシーとプライベート ポリシーに分割されます。
パブリック ポリシーはベンダーにエクスポートされます。タイプと属性は安定版 API になっており、ベンダー ポリシーはパブリック ポリシーのタイプと属性を参照できます。タイプは PLATFORM_SEPOLICY_VERSION
に基づいてバージョニングされ、バージョニングされたポリシーがベンダー ポリシーに含められます。元のポリシーは、system_ext パーティションと product パーティションにそれぞれ含められます。
プライベート ポリシーには、system_ext 専用および product 専用のタイプ、権限、system_ext パーティションと product パーティションの機能に必要な属性が含まれています。プライベート ポリシーはベンダーからは参照できません。つまり、これらのルールは内部的であり、変更可能です。
system_ext と product のマッピング
system_ext と product は、指定されたパブリック タイプをベンダーにエクスポートできます。ただし、互換性を維持する責任は各パートナーにあります。互換性を維持するため、パートナーは各自のマッピング ファイルを提供して、以前のバージョンのバージョニングされた属性を現在のパブリック sepolicy で使用されるコンクリート タイプにマッピングできます。
- system_ext のマッピング ファイルをインストールするには、目的のマッピング情報を含む cil ファイルを
{SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil
に配置し、system_ext_{ver}.cil
をPRODUCT_PACKAGES
に追加します。 - product のマッピング ファイルをインストールするには、目的のマッピング情報を含む cil ファイルを
{PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil
に配置し、product_{ver}.cil
をPRODUCT_PACKAGES
に追加します。
Redbull デバイスの product パーティションのマッピング ファイルを追加する例をご覧ください。
プリコンパイル済みの SELinux ポリシー
init
が SELinux を有効にする前に、init
はすべての CIL ファイルをパーティション(system
、system_ext
、product
、vendor
、odm
)から収集して、カーネルにロードできるバイナリ形式のポリシーにコンパイルします。コンパイルには時間がかかるため(通常は 1~2 秒)、CIL ファイルはビルド時にプリコンパイルされ、入力 CIL ファイルの SHA256 ハッシュとともに、/vendor/etc/selinux/precompiled_sepolicy
または /odm/etc/selinux/precompiled_sepolicy
のいずれかに配置されます。init
は実行時にハッシュを比較して、いずれかのポリシー ファイルが更新されたかどうかを確認します。何も変更がなければ、init
はプリコンパイル済みのポリシーを読み込みます。変更があれば、init
は直ちにそのポリシーをコンパイルし、プリコンパイル済みのポリシーの代わりにそれを使用します。
もっと詳しく説明すると、プリコンパイル済みのポリシーが使用されるのは、以下の条件がすべて満たされる場合です。ここで、{partition}
はプリコンパイル済みのポリシーが存在するパーティション(vendor
または odm
)を表します。
-
/system/etc/selinux/plat_sepolicy_and_mapping.sha256
と/{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256
の両方が存在し、互いに等しい。 -
/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256
と/{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256
が両方とも存在しない。または、両方が存在し、互いに等しい。 -
/product/etc/selinux/product_sepolicy_and_mapping.sha256
と/{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256
が両方とも存在しない。または、両方が存在し、互いに等しい。
上記のいずれかが異なる場合、init
はデバイス上のコンパイルパスにフォールバックします。詳しくは、system/core/init/selinux.cpp
をご覧ください。