SELinux の実装

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 、拡張属性をサポートしないprocvfatなどのファイルシステムにラベルを割り当てます。この設定はカーネル ポリシーの一部としてロードされますが、変更はコア内の 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 を始めるには:

  1. カーネルで SELinux を有効にします: CONFIG_SECURITY_SELINUX=y
  2. kernel_cmdline または bootconfig パラメータを次のように変更します。
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    または
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    これは、デバイスのポリシーの初期開発専用です。初期ブートストラップ ポリシーを作成したら、このパラメータを削除して、デバイスに強制を適用しないと CTS が失敗します。
  3. システムを許可モードで起動し、起動時にどのような拒否が発生するかを確認します。
    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
    
  4. 出力を評価して、 init: Warning! Service name needs a SELinux domain defined; please fix!に似た警告がないか確認します。 init: Warning! Service name needs a SELinux domain defined; please fix!手順とツールについては、 「検証」を参照してください。
  5. ラベル付けが必要なデバイスおよびその他の新しいファイルを特定します。
  6. オブジェクトに既存または新しいラベルを使用します。 *_contextsファイルを参照して、以前にどのようにラベルが付けられていたかを確認し、ラベルの意味の知識を利用して新しいラベルを割り当てます。理想的には、これはポリシーに適合する既存のラベルですが、場合によっては新しいラベルが必要になり、そのラベルにアクセスするためのルールが必要になります。ラベルを適切なコンテキスト ファイルに追加します。
  7. 独自のセキュリティ ドメインを持つ必要があるドメイン/プロセスを特定します。おそらく、それぞれに対してまったく新しいポリシーを作成する必要があります。たとえば、 initから生成されたすべてのサービスには、独自のサービスが必要です。次のコマンドは、実行中のサービスを明らかにするのに役立ちます (ただし、すべてのサービスでそのような処理が必要です)。
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. init. device .rc使用して、ドメイン タイプを持たないドメインを識別します。 initにルールを追加したり、 initアクセスを独自のポリシー内のアクセスと混同したりすることを避けるために、開発プロセスの早い段階でドメインを与えます。
  9. BOARD_SEPOLICY_*変数を使用するようにBOARD_CONFIG.mkを設定します。この設定の詳細については、 system/sepolicyREADME を参照してください。
  10. 初期化を調べます。 device .rc および fstab。 deviceファイルを作成し、 mountのすべての使用が適切にラベル付けされたファイルシステムに対応していること、またはcontext= mountオプションが指定されていることを確認してください。
  11. それぞれの拒否を確認し、それぞれを適切に処理する SELinux ポリシーを作成します。 「カスタマイズ」の例を参照してください。

AOSP のポリシーから始めて、それを基にして独自のカスタマイズを行う必要があります。ポリシー戦略の詳細とこれらの手順の詳細については、 「 SELinux ポリシーの作成 」を参照してください。

ユースケース

独自のソフトウェアおよび関連する SELinux ポリシーを作成するときに考慮すべきエクスプロイトの具体的な例を次に示します。

シンボリックリンク- シンボリックリンクはファイルとして表示されるため、多くの場合ファイルとして読み取られ、エクスプロイトにつながる可能性があります。たとえば、 initなどの一部の特権コンポーネントは、特定のファイルのアクセス許可を変更し、場合によっては過度にオープンになることがあります。

その後、攻撃者はそれらのファイルを制御するコードへのシンボリックリンクに置き換え、攻撃者が任意のファイルを上書きできるようにする可能性があります。ただし、アプリケーションがシンボリックリンクを決して通過しないことがわかっている場合は、SELinux を使用してシンボリックリンクの通過を禁止できます。

システム ファイル- システム サーバーによってのみ変更される必要があるシステム ファイルのクラスを考慮してください。それでも、 netdinit 、およびvold root として実行されるため、これらのシステム ファイルにアクセスできます。そのため、 netdが侵害された場合、それらのファイルが侵害され、場合によってはシステム サーバー自体も侵害される可能性があります。

SELinux を使用すると、これらのファイルをシステム サーバー データ ファイルとして識別できます。したがって、それらへの読み取り/書き込みアクセス権を持つ唯一のドメインはシステム サーバーです。 netdが侵害された場合でも、root として実行されているにもかかわらず、ドメインをシステム サーバー ドメインに切り替えてそれらのシステム ファイルにアクセスすることはできません。

アプリ データ- もう 1 つの例は、root として実行する必要があるがアプリ データにアクセスすべきではない関数のクラスです。これは、アプリケーション データに関係のない特定のドメインのインターネットへのアクセスを禁止するなど、幅広いアサーションを行うことができるため、非常に便利です。

setattr - chmodchownなどのコマンドの場合、関連するドメインがsetattrを実行できるファイルのセットを識別できます。これ以外のものは、たとえ root であっても、これらの変更を禁止される可能性があります。したがって、アプリケーションは、ラベル付きのapp_data_filesに対してchmodおよびchownを実行する可能性がありますが、 shell_data_filesまたはsystem_data_filesに対しては実行しない可能性があります。