Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

SELinux のカスタマイズ

基本レベルの SELinux 機能を統合し、結果をくまなく分析した後は、Android オペレーティング システムにカスタマイズを適用する、独自のポリシー設定を追加できます。こうしたポリシーも、Android 互換性プログラムの要件に適合する必要があり、デフォルトの SELinux 設定を削除することはできません。

メーカーは既存の SELinux ポリシーを削除しないでください。削除すると、Android SELinux の実装と管理対象のアプリケーションに問題が発生する可能性があります。その影響はサードパーティ アプリケーションにも及び、コンプライアンスに適合させて正常に動作させるために、改良が必要になることもあります。SELinux 対応デバイスで継続して動作させるためにアプリケーションの変更が必要になる、という状況は避けなければなりません。

SELinux のカスタマイズを行う場合は、以下のことを行ってください。

  • すべての新しいデーモンについて SELinux ポリシーを作成する
  • 適切な場合は常に事前定義されたドメインを使用する
  • init サービスとして生成されたすべてのプロセスにドメインを割り当てる
  • ポリシーを作成する前にマクロについて熟知する
  • コアポリシーの変更を AOSP に送信する

また次のことは行わないでください。

  • 互換性のないポリシーを作成する
  • エンドユーザーによるポリシーのカスタマイズを許可する
  • MDM ポリシーのカスタマイズを許可する
  • ポリシー違反に関してユーザーに不安を与える
  • バックドアを追加する

具体的な要件については、Android 互換性定義ドキュメントのカーネル セキュリティ機能のセクションをご覧ください。

SELinux ではホワイトリスト型のアプローチが採用されています。これは、アクセス権はすべて、ポリシーによって明示的に許可されたうえで付与されるということを意味します。Android のデフォルトの SELinux ポリシーで、すでに Android オープンソース プロジェクトがサポートされているため、SELinux 設定を変更する必要はありません。SELinux 設定をカスタマイズする場合には、既存のアプリケーションに問題が発生しないように十分に注意する必要があります。手順:

  1. 最新の Android カーネルを使用します。
  2. 最小限の権限の原則を採用します。
  3. Android に独自に追加した要素だけを扱います。デフォルトのポリシーは、Android オープンソース プロジェクトのコードベースと自動的に連動します。
  4. ソフトウェア コンポーネントを、1 つのタスクを実行するモジュールに分割します。
  5. それらのタスクを関連のない機能から分離する SELinux ポリシーを作成します。
  6. 作成したポリシーを /device/manufacturer/device-name/sepolicy ディレクトリ内の *.te ファイル(SELinux ポリシー ソースファイルの拡張)に格納し、BOARD_SEPOLICY 変数を使用してビルドに組み込みます。
  7. 新しいドメインは最初に permissive にします。permissive にするは、ドメインの .te ファイル内で permissive 宣言を使用します。
  8. 結果を分析し、ドメインの定義を改良します。
  9. userdebug ビルドで拒否が発生しなくなったら、permissive 宣言を削除します。

SELinux ポリシーの変更を統合したら、SELinux の互換性を維持するためのステップを開発ワークフローに追加してください。実際の実装ではなく、ソフトウェア モデルに変更があった場合にのみ SELinux ポリシーを変更するのが、理想的なソフトウェア開発プロセスです。

SELinux のカスタマイズを開始したら、最初に Android への追加に対する監査を行います。新しい機能を実行するコンポーネントを追加した場合は、enforcing モードを有効にする前に、そのコンポーネントが Android のセキュリティ ポリシーと、OEM が作成した関連するポリシーに準拠していることを確認します。

望ましくない問題の発生を防ぐために、制限を厳格にしすぎて互換性を低下させてデバイスの機能を損なわせるよりも、制限を緩和して互換性を高めたほうが得策です。むしろ、他のアプリケーションにも利点になるような変更であれば、デフォルトの SELinux ポリシーにパッチとして送信するべきです。デフォルトのセキュリティ ポリシーにパッチが適用されると、新しい Android がリリースされるたびに変更を適用する必要がなくなります。

ポリシー ステートメントの例

SELinux は M4 コンピュータ言語に基づいているため、各種の効率的なマクロをサポートしています。

次の例では、すべてのドメインに /dev/null に対する読み取りと書き込みアクセス権、/dev/zero に対する読み取りアクセス権を付与しています。

    # Allow read / write access to /dev/null
    allow domain null_device:chr_file { getattr open read ioctl lock append write};

    # Allow read-only access to /dev/zero
    allow domain zero_device:chr_file { getattr open read ioctl lock };
    

これと同じステートメントを、SELinux *_file_perms マクロ(短縮形)によって記述できます。

    # Allow read / write access to /dev/null
    allow domain null_device:chr_file rw_file_perms;

    # Allow read-only access to /dev/zero
    allow domain zero_device:chr_file r_file_perms;
    

ポリシーの例

DHCP 用の完全なポリシーの例を示します。

    type dhcp, domain;
    permissive dhcp;
    type dhcp_exec, exec_type, file_type;
    type dhcp_data_file, file_type, data_file_type;

    init_daemon_domain(dhcp)
    net_domain(dhcp)

    allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service
    };
    allow dhcp self:packet_socket create_socket_perms;
    allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write };
    allow dhcp shell_exec:file rx_file_perms;
    allow dhcp system_file:file rx_file_perms;
    # For /proc/sys/net/ipv4/conf/*/promote_secondaries
    allow dhcp proc_net:file write;
    allow dhcp system_prop:property_service set ;
    unix_socket_connect(dhcp, property, init)

    type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
    allow dhcp dhcp_data_file:dir create_dir_perms;
    allow dhcp dhcp_data_file:file create_file_perms;

    allow dhcp netd:fd use;
    allow dhcp netd:fifo_file rw_file_perms;
    allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write };
    allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket
    netlink_nflog_socket } { read write };
    

ポリシーの例を細かく分けて見てみましょう。

最初の型宣言の行では、DHCP デーモンが基本セキュリティ ポリシーから継承します(domain)。前のステートメントの例のように、DHCP は /dev/null に対して読み取りと書き込みが可能です。

2 行目では、DHCP が permissive ドメインとして指定されています。

init_daemon_domain(dhcp) の行では、DHCP が init から生成され、それとの通信が可能であることを示しています。

net_domain(dhcp) の行では、DHCP が TCP パケットの読み取りと書き込み、ソケット経由の通信、DNS リクエストの実行などの一般的なネットワーク機能を net ドメインから使用することを許可しています。

allow dhcp proc_net:file write; の行では、DHCP が /proc 内の特定のファイルに書き込めることを示しています。この行は、SELinux でファイルのきめ細かいラベル付けが可能であることを示しています。ここでは proc_net ラベルを使用して、書き込みアクセス権の対象を /proc/sys/net 以下のファイルに限定しています。

allow dhcp netd:fd use; で始まる最終ブロックは、アプリケーションの相互の通信がどのように許可されるかを示しています。このポリシーは、ファイル記述子、FIFO ファイル、データグラム ソケット、UNIX ストリーム ソケット経由で、DHCP と netd が通信できることを示しています。DHCP はデータグラム ソケットと UNIX ストリーム ソケットに対して読み取りと書き込みのみが可能で、それらを作成したり開いたりすることはできません。

使用可能なコントロール

クラス 権限
ファイル

    ioctl read write create getattr setattr lock relabelfrom relabelto append
    unlink link rename execute swapon quotaon mounton
ディレクトリ

    add_name remove_name reparent search rmdir open audit_access execmod
ソケット

    ioctl read write create getattr setattr lock relabelfrom relabelto append bind
    connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg
    name_bind
ファイル システム

    mount remount unmount getattr relabelfrom relabelto transition associate
    quotamod quotaget
プロセス

    fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched
    getsession getpgid setpgid getcap setcap share getattr setexec setfscreate
    noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem
    execstack execheap setkeycreate setsockcreate
セキュリティ

    compute_av compute_create compute_member check_context load_policy
    compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
    read_policy
機能

    chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap
    linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock
    ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin
    sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write
    audit_control setfcap

もっと見る

その他

neverallow ルール

SELinux neverallow ルールは、起きてはならない動作を禁止します。互換性テストにより、SELinux neverallow ルールをすべてのデバイスに確実に適用できるようになりました。

次のガイドラインにより、メーカーはカスタマイズ中に neverallow ルールに関連するエラーを回避できます。ここに示すルール番号は Android 5.1 に対応しているため、リリースに応じて変わる場合があります。

ルール 48: neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
ptrace の man ページをご覧ください。sys_ptrace 機能によって、すべてのプロセスに対して ptrace を適用できます。他のプロセスに対する大幅な制御が可能になるため、ルールで指定されたシステム コンポーネントに対してのみ適用する必要があります。この機能が必要になるのは、ほとんどの場合、ユーザー向けビルド用ではないものや、不要な機能が存在するときです。不要なコンポーネントを削除してください。

ルール 76: neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
このルールは、システム上で任意のコードの実行を防止するものです。特に、/system のコードだけが実行されることが示されているため、セキュアブートなどの仕組みによってセキュリティが保証されます。この neverallow ルールで問題が発生した場合、最良の解決方法は、問題のコードを /system パーティションに移動させることです。

Android 8.0 以降での SEPolicy のカスタマイズ

このセクションでは、Android 8.0 以降でのベンダー SELinux ポリシーに関するガイドラインを示します。Android オープンソース プロジェクト(AOSP)SEPolicy と SEPolicy 拡張の詳細も含まれています。複数のパーティションと Android のバージョンにわたって SELinux ポリシーの互換性を維持する方法について詳しくは、互換性をご覧ください。

ポリシーの配置

Android 7.0 以前では、さまざまなデバイスタイプを対象として AOSP ポリシーを強化するポリシーなど、デバイス メーカーが BOARD_SEPOLICY_DIRS にポリシーを追加できました。Android 8.0 以降では、BOARD_SEPOLICY_DIRS にポリシーを追加すると、ベンダー イメージだけにポリシーが配置されます。

Android 8.0 以降では、ポリシーは AOSP 内の次の場所に存在します。

  • system/sepolicy/public。ベンダー固有のポリシーで使用するためにエクスポートされたポリシーが含まれます。すべてが Android 8.0 の互換性インフラストラクチャに配置されます。パブリック ポリシーはリリース間で維持されるため、カスタマイズされたポリシーに任意の /public を含めることができます。そのため、/public に配置できるポリシーのタイプは、さらに制限されます。これはプラットフォームのエクスポートされたポリシー API として考えることができます。/system/vendor 間のインターフェースを扱うものがすべてここに含まれます。
  • system/sepolicy/private。システム イメージの機能に必要なポリシーが含まれますが、どのベンダー イメージかは、ポリシーは認識できません。
  • system/sepolicy/vendor/vendor に格納されるが、コアプラットフォーム ツリー(デバイス固有のディレクトリではなく)に存在するコンポーネント用のポリシーが含まれます。これは、ビルドシステムによるデバイスとグローバル コンポーネント間の区別を表すアーティファクトです。コンセプトとしては、以下に示すデバイス固有のポリシーの一部になっています。
  • device/manufacturer/device-name/sepolicy。デバイス固有のポリシーが含まれています。デバイスに応じたポリシーのカスタマイズも含まれます。Android 8.0 以降では、ベンダー イメージのコンポーネントのポリシーに相当します。

サポートされているポリシーのシナリオ

Android 8.0 以降搭載のデバイスでは、ベンダー イメージは、OEM のシステム イメージ、および Google が提供するリファレンス AOSP システム イメージに対応している必要があります(このリファレンス イメージの CTS にパスする必要があります)。こうした要件により、フレームワークとベンダーコードが明確に分離されます。Android 8.0 以降のデバイスでは次のシナリオがサポートされます。

ベンダー イメージ専用の拡張機能

: ベンダー イメージからのプロセスをサポートするベンダー イメージの vndservicemanager に新しいサービスを追加します。

以前の Android バージョンを搭載したデバイスと同様に、device/manufacturer/device-name/sepolicy にデバイス固有のカスタマイズを追加します。ベンダー コンポーネント間のみのインタラクションを管理する新しいポリシーでは、device/manufacturer/device-name/sepolicy だけに存在するタイプを含める必要があります。ここに示すポリシーでは、ベンダーのコードの動作を許可しています。このポリシーはフレームワーク専用の OTA の一部としては更新されず、リファレンス AOSP システム イメージと合わせて、デバイス上の結合されたポリシーに含まれます。

AOSP と連動するベンダー イメージのサポート

: AOSP で定義された HAL を実装する新しいプロセス(ベンダー イメージから hwservicemanager に登録)を追加します。

以前の Android バージョンを搭載したデバイスと同様に、device/manufacturer/device-name/sepolicy でデバイス固有のカスタマイズを実行します。system/sepolicy/public/ の一部としてエクスポートされたポリシーを使用できます。デバイスの出荷時には、これはベンダー ポリシーの一部として扱われます。パブリック ポリシーから得られたタイプと属性は、neverallow による制限に従い、新しいベンダー固有の要素と連動する方法を示す新しいルールで使用できます。ベンダー固有のケースと同様に、この新しいポリシーはフレームワーク専用の OTA の一部としては更新されず、リファレンス AOSP システム イメージと合わせて、デバイス上で結合されたポリシーに含まれます。

システム イメージ専用の拡張機能

: システム イメージから他のプロセスによってのみアクセスされる新しいサービス(servicemanager によって登録される)を追加します。

このポリシーを system/sepolicy/private に追加します。パートナー システム イメージにおいて機能を有効にするプロセスやオブジェクトをさらに追加することもできます。ただしそれらの新しい要素が、ベンダー イメージの新しいコンポーネントとのインタラクションを必要としない場合に限ります(特にそうしたプロセスまたはオブジェクトは、ベンダー イメージからのポリシーがなくても完全に機能する必要があります)。system/sepolicy/public によってエクスポートされたポリシーは、ここでもベンダー イメージ専用の拡張機能と同様に使用できます。このポリシーはシステム イメージの一部であり、フレームワーク専用の OTA で更新できますが、リファレンス AOSP のシステム イメージを使用する場合には存在しません。

拡張 AOSP コンポーネントに対応するベンダー イメージの拡張機能

例: AOSP システム イメージ内に存在する拡張クライアント(拡張システム サーバーなど)が使用できる新しい非 AOSP HAL。

システムとベンダー間のインタラクションに関するポリシーを、デバイスの出荷時にベンダー パーティションに存在する device/manufacturer/device-name/sepolicy ディレクトリに含める必要があります。これは、リファレンス AOSP イメージと連動するようにベンダー イメージのサポートを追加する上記のシナリオと似ていますが、変更された AOSP コンポーネントがシステム パーティションのその他の部分と正常に連動するために、追加のポリシーを必要とする点が異なります(パブリック AOSP タイプのラベルが付与されている場合は不要です)。

パブリック AOSP コンポーネントとシステム イメージ専用の拡張機能とのインタラクションに関するポリシーが system/sepolicy/private に必要です。

AOSP インターフェースだけにアクセスできる、システム イメージ用の拡張機能

例: 新しい非 AOSP システム プロセスは、AOSP が依存する HAL にアクセスできなければなりません。

これはシステム イメージ専用の拡張機能の例に似ていますが、新しいシステム コンポーネントが system/vendor インターフェースを超えて接点をもつ可能性がある点が異なります。新しいシステム コンポーネント用のポリシーは system/sepolicy/private に配置されます。これは、AOSP によって(機能に必要なタイプと属性が含まれている)system/sepolicy/public で確立されているインターフェースを通じて行う場合にのみ許可されます。ポリシーはデバイス固有のポリシーに含めることができますが、他の system/sepolicy/private タイプを使用したり、フレームワークのみの更新の結果として(ポリシーに影響する方法で)変更したりすることはできません。ポリシーはフレームワークのみの OTA で変更することはできますが、AOSP システム イメージを使用する場合には存在しません(AOSP システム イメージにも新しいシステム コンポーネントが存在しません)。

新しいシステム コンポーネントに対応するベンダー イメージの拡張機能

例: AOSP アナログがない(そのために独自のドメインを必要とする)クライアント プロセスで使用する、新しい非 AOSP HAL を追加します。

AOSP-の拡張機能の例と同様に、システムとベンダー間のインタラクションに関するポリシーは、デバイスの発送時にベンダー パーティションに存在する device/manufacturer/device-name/sepolicy ディレクトリに配置する必要があります(システム ポリシーがベンダー固有の詳細情報を認識できないようにするため)。system/sepolicy/public のポリシーを拡張する新しいパブリック タイプを追加できます。これは、既存の AOSP ポリシーに追加する形でのみ可能です。AOSP パブリック ポリシーは削除しないでください。それにより、system/sepolicy/private および device/manufacturer/device-name/sepolicy のポリシーに対して新しいパブリック タイプを使用できます。

system/sepolicy/public に追加するたびに、新しい互換性保証をマッピング ファイルで追跡する必要があり、また他の制限も加わるため、複雑性が増大することに注意してください。system/sepolicy/public には、新しいタイプと、対応する許可ルールのみ追加できます。属性やその他のポリシー ステートメントはサポートされていません。さらに、新しいパブリック タイプは、/vendor ポリシーでオブジェクトに直接ラベル付けするためには使用できません。

サポートされていないポリシー シナリオ

Android 8.0 以降を搭載したデバイスでは、次のポリシー シナリオやポリシー例をサポートしていません。

フレームワークのみの OTA 後に新しいベンダーイメージ コンポーネントに対する権限を必要とするシステム イメージへの拡張機能の追加

例: 独自のドメインを必要とする新しい非 AOSP システム プロセスが、次回の Android リリースに追加され、新しい非 AOSP HAL へのアクセスを必要とする場合。

新しい(非 AOSP)システムとベンダー コンポーネント間のインタラクションと似ていますが、新しいシステムタイプがフレームワークのみの OTA で導入される点が異なります。新しいタイプは system/sepolicy/public 内のポリシーに追加できますが、既存のベンダー ポリシーは Android 8.0 システムのパブリック ポリシーだけを追跡しているため、新しいタイプを認識しません。AOSP では、ベンダーが提供するリソースを属性(hal_foo 属性など)によって公開することでこれを処理しますが、system/sepolicy/public では属性パートナー拡張機能はサポートされていないため、この方法はベンダー ポリシーでは使用できません。アクセスは既存のパブリック タイプによって可能にする必要があります。

例: システム プロセス(AOSP または非 AOSP)の変更によって、新しい非 AOSP ベンダー コンポーネントとのインタラクションも変更する必要がある場合。

システム イメージ上のポリシーは、特定のベンダーによるカスタマイズを考慮せずに作成する必要があります。AOSP の特定のインターフェースに関するポリシーは、system/sepolicy/public の属性を通じて公開されます。これにより、ベンダー ポリシーがそれらの属性を使用する将来のシステム ポリシーをオプトインできます。ただし system/sepolicy/public の属性拡張はサポートされていないため、システム コンポーネントと新しいベンダー コンポーネント(AOSP system/sepolicy/public にすでに存在する属性によって処理されない)との間のインタラクションを規定するすべてのポリシーは、device/manufacturer/device-name/sepolicy に配置する必要があります。つまりシステムタイプは、フレームワークのみの OTA の一部として、ベンダータイプに付与されたアクセス権を変更することはできません。