SELinux はデフォルト拒否に設定されています。これは、カーネル内にフックがあるすべてのアクセスをポリシーによって明示的に許可する必要があることを意味します。これは、ポリシー ファイルがルール、タイプ、クラス、権限などに関する大量の情報で構成されていることを意味します。 SELinux の完全な考察はこのドキュメントの範囲外ですが、新しい Android デバイスを立ち上げる際には、ポリシー ルールの記述方法を理解することが不可欠です。 SELinux に関しては、すでに大量の情報が入手可能です。推奨されるリソースについては、サポート ドキュメントを参照してください。
キーファイル
SELinux を有効にするには、最新の Android カーネルを統合し、 system/sepolicyディレクトリにあるファイルを組み込みます。コンパイルされると、これらのファイルは SELinux カーネル セキュリティ ポリシーを構成し、アップストリームの Android オペレーティング システムをカバーします。
一般に、 system/sepolicy
ファイルを直接変更しないでください。代わりに、 /device/ manufacturer / device-name /sepolicy
ディレクトリに独自のデバイス固有のポリシー ファイルを追加または編集します。 Android 8.0 以降では、これらのファイルに加えた変更は、ベンダー ディレクトリ内のポリシーにのみ影響します。 Android 8.0 以降でのパブリック sepolicy の分離の詳細については、 「Android 8.0 以降での SEPolicy のカスタマイズ」を参照してください。 Android のバージョンに関係なく、次のファイルを引き続き変更します。
ポリシーファイル
*.te
で終わるファイルは SELinux ポリシー ソース ファイルで、ドメインとそのラベルを定義します。 /device/ manufacturer / device-name /sepolicy
に新しいポリシー ファイルを作成する必要がある場合がありますが、可能な場合は既存のファイルを更新するようにしてください。
コンテキストファイル
コンテキスト ファイルでは、オブジェクトのラベルを指定します。
-
file_contexts
ファイルにラベルを割り当て、さまざまなユーザー空間コンポーネントによって使用されます。新しいポリシーを作成するときは、このファイルを作成または更新して、ファイルに新しいラベルを割り当てます。新しいfile_contexts
を適用するには、ファイルシステム イメージを再構築するか、ラベルを変更するファイルに対してrestorecon
を実行します。アップグレードの際、file_contexts
への変更は、アップグレードの一部としてシステム パーティションとユーザーデータ パーティションに自動的に適用されます。また、restorecon_recursive
呼び出しを init に追加することで、他のパーティションへのアップグレード時に変更を自動的に適用することもできます。パーティションが読み書き可能にマウントされた後のboard .rcファイル。 -
genfs_contexts
、拡張属性をサポートしないproc
やvfat
などのファイルシステムにラベルを割り当てます。この設定はカーネル ポリシーの一部としてロードされますが、変更はコア内の i ノードには反映されない可能性があり、変更を完全に適用するには再起動するか、ファイル システムをアンマウントしてから再マウントする必要があります。context=mount
オプションを使用したvfat
など、特定のラベルを特定のマウントに割り当てることもできます。 -
property_contexts
、Android システム プロパティにラベルを割り当てて、どのプロセスがラベルを設定できるかを制御します。この構成は、起動時にinit
プロセスによって読み取られます。 -
service_contexts
Android バインダー サービスにラベルを割り当てて、どのプロセスがサービスのバインダー参照を追加 (登録) および検索 (検索) できるかを制御します。この構成は、起動時にservicemanager
プロセスによって読み取られます。 -
seapp_contexts
、アプリ プロセスと/data/data
ディレクトリにラベルを割り当てます。この構成は、アプリの起動ごとにzygote
プロセスによって読み取られ、起動時にinstalld
によって読み取られます。 -
mac_permissions.xml
アプリの署名と、必要に応じてパッケージ名に基づいて、アプリにseinfo
タグを割り当てます。seinfo
タグをseapp_contexts
ファイル内のキーとして使用して、そのseinfo
タグを持つすべてのアプリに特定のラベルを割り当てることができます。この構成は、起動時にsystem_server
によって読み取られます。 -
keystore2_key_contexts
Keystore 2.0 名前空間にラベルを割り当てます。これらの名前空間は、keystore2 デーモンによって強制されます。キーストアは常に UID/AID ベースの名前空間を提供してきました。 Keystore 2.0 は、sepolicy で定義された名前空間をさらに強制します。このファイルの形式と規則の詳細な説明は、ここで参照できます。
BoardConfig.mk メイクファイル
ポリシー ファイルとコンテキスト ファイルを編集または追加した後、 sepolicy
サブディレクトリと各新しいポリシー ファイルを参照するように/device/ manufacturer / device-name /BoardConfig.mk
メイクファイルを更新します。 BOARD_SEPOLICY
変数の詳細については、 system/sepolicy/README
ファイルを参照してください。
BOARD_SEPOLICY_DIRS += \ <root>/device/manufacturer/device-name/sepolicy BOARD_SEPOLICY_UNION += \ genfs_contexts \ file_contexts \ sepolicy.te
再構築後、デバイスで SELinux が有効になります。これで、 「カスタマイズ」で説明したように Android オペレーティング システムへの独自の追加に合わせて SELinux ポリシーをカスタマイズしたり、 「検証」で説明したように既存の設定を検証したりできます。
新しいポリシー ファイルと BoardConfig.mk の更新が完了すると、新しいポリシー設定が最終的なカーネル ポリシー ファイルに自動的に組み込まれます。デバイス上で sepolicy を構築する方法の詳細については、 「sepolicy の構築」を参照してください。
実装
SELinux を始めるには:
- カーネルで SELinux を有効にします:
CONFIG_SECURITY_SELINUX=y
- kernel_cmdline または bootconfig パラメータを次のように変更します。
BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
またはBOARD_BOOTCONFIG := androidboot.selinux=permissive
これは、デバイスのポリシーの初期開発専用です。初期ブートストラップ ポリシーを作成したら、このパラメータを削除して、デバイスに強制を適用しないと CTS が失敗します。 - システムを許可モードで起動し、起動時にどのような拒否が発生するかを確認します。
Ubuntu 14.04 以降の場合:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
Ubuntu 12.04 の場合:adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- 出力を評価して、
init: Warning! Service name needs a SELinux domain defined; please fix!
に似た警告がないか確認します。init: Warning! Service name needs a SELinux domain defined; please fix!
手順とツールについては、 「検証」を参照してください。 - ラベル付けが必要なデバイスおよびその他の新しいファイルを特定します。
- オブジェクトに既存または新しいラベルを使用します。
*_contexts
ファイルを参照して、以前にどのようにラベルが付けられていたかを確認し、ラベルの意味の知識を利用して新しいラベルを割り当てます。理想的には、これはポリシーに適合する既存のラベルですが、場合によっては新しいラベルが必要になり、そのラベルにアクセスするためのルールが必要になります。ラベルを適切なコンテキスト ファイルに追加します。 - 独自のセキュリティ ドメインを持つ必要があるドメイン/プロセスを特定します。おそらく、それぞれに対してまったく新しいポリシーを作成する必要があります。たとえば、
init
から生成されたすべてのサービスには、独自のサービスが必要です。次のコマンドは、実行中のサービスを明らかにするのに役立ちます (ただし、すべてのサービスでそのような処理が必要です)。adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
-
init. device .rc
使用して、ドメイン タイプを持たないドメインを識別します。init
にルールを追加したり、init
アクセスを独自のポリシー内のアクセスと混同したりすることを避けるために、開発プロセスの早い段階でドメインを与えます。 -
BOARD_SEPOLICY_*
変数を使用するようにBOARD_CONFIG.mk
を設定します。この設定の詳細については、system/sepolicy
のREADME を参照してください。 - 初期化を調べます。 device .rc および fstab。 deviceファイルを作成し、
mount
のすべての使用が適切にラベル付けされたファイルシステムに対応していること、またはcontext= mount
オプションが指定されていることを確認してください。 - それぞれの拒否を確認し、それぞれを適切に処理する SELinux ポリシーを作成します。 「カスタマイズ」の例を参照してください。
AOSP のポリシーから始めて、それを基にして独自のカスタマイズを行う必要があります。ポリシー戦略の詳細とこれらの手順の詳細については、 「 SELinux ポリシーの作成 」を参照してください。
ユースケース
独自のソフトウェアおよび関連する SELinux ポリシーを作成するときに考慮すべきエクスプロイトの具体的な例を次に示します。
シンボリックリンク- シンボリックリンクはファイルとして表示されるため、多くの場合ファイルとして読み取られ、エクスプロイトにつながる可能性があります。たとえば、 init
などの一部の特権コンポーネントは、特定のファイルのアクセス許可を変更し、場合によっては過度にオープンになることがあります。
その後、攻撃者はそれらのファイルを制御するコードへのシンボリックリンクに置き換え、攻撃者が任意のファイルを上書きできるようにする可能性があります。ただし、アプリケーションがシンボリックリンクを決して通過しないことがわかっている場合は、SELinux を使用してシンボリックリンクの通過を禁止できます。
システム ファイル- システム サーバーによってのみ変更される必要があるシステム ファイルのクラスを考慮してください。それでも、 netd
、 init
、およびvold
root として実行されるため、これらのシステム ファイルにアクセスできます。そのため、 netd
が侵害された場合、それらのファイルが侵害され、場合によってはシステム サーバー自体も侵害される可能性があります。
SELinux を使用すると、これらのファイルをシステム サーバー データ ファイルとして識別できます。したがって、それらへの読み取り/書き込みアクセス権を持つ唯一のドメインはシステム サーバーです。 netd
が侵害された場合でも、root として実行されているにもかかわらず、ドメインをシステム サーバー ドメインに切り替えてそれらのシステム ファイルにアクセスすることはできません。
アプリ データ- もう 1 つの例は、root として実行する必要があるがアプリ データにアクセスすべきではない関数のクラスです。これは、アプリケーション データに関係のない特定のドメインのインターネットへのアクセスを禁止するなど、幅広いアサーションを行うことができるため、非常に便利です。
setattr - chmod
やchown
などのコマンドの場合、関連するドメインがsetattr
を実行できるファイルのセットを識別できます。これ以外のものは、たとえ root であっても、これらの変更を禁止される可能性があります。したがって、アプリケーションは、ラベル付きのapp_data_files
に対してchmod
およびchown
を実行する可能性がありますが、 shell_data_files
またはsystem_data_files
に対しては実行しない可能性があります。