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

ポリシーの互換性

この記事では、Android がプラットフォーム OTA におけるポリシーの互換性の問題を処理する方法を説明します。互換性の問題は、新しいプラットフォーム SELinux 設定が、従来のベンダー SELinux 設定と異なる場合に生じます。

Treble ベースの SELinux ポリシー設計では、プラットフォームとベンダー ポリシー間のバイナリ差異が考慮されます。ベンダー パーティションによって依存関係が生成される場合(platform < vendor < oem など)、スキームがさらに複雑化します。

Android 8.0 以降では、SELinux グローバル ポリシーはプライベート コンポーネントとパブリック コンポーネントに分割されます。パブリック コンポーネントは、ポリシーおよび関連するインフラストラクチャで構成されています。これらは特定のプラットフォーム バージョンで利用できることが保証されています。このポリシーは、ベンダー ポリシーの作成者に公開され、ベンダーはこれに基づいてベンダー ポリシー ファイルを作成します。これをプラットフォームから提供されるポリシーと組み合わせることで、デバイスに対して完全に機能するポリシーができあがります。

  • バージョニングの場合は、エクスポートされたプラットフォーム パブリック ポリシーが属性として記述されます。
  • ポリシーの記述を容易にするため、エクスポートされたタイプはポリシー作成プロセスの一環として、バージョニングされた属性に変換されます。パブリック タイプは、ベンダーのコンテキスト ファイルによるラベル付けの決定に直接使用できます。

Android では、プラットフォーム ポリシーでエクスポートされたコンクリート タイプと、それに対応する、プラットフォーム バージョンごとにバージョニングされた属性とのマッピングが維持されます。そのため、オブジェクトがタイプによってラベル付けされていても、前のバージョンのプラットフォーム パブリック ポリシーで保証されていた動作が機能しなくなるということはありません。このマッピングは、プラットフォームのバージョンごとにマッピング ファイルを最新にすることで維持されます。それにより、パブリック ポリシーでエクスポートされた各タイプの属性メンバーシップ情報が保持されます。

オブジェクトのオーナーシップとラベル付け

Android 8.0 以降でポリシーをカスタマイズする場合、プラットフォームとベンダー ポリシーを分離するために、オブジェクトごとにオーナーシップを明確に定義する必要があります。たとえば、ベンダーが /dev/foo とラベル付けし、その後 OTA でプラットフォームが /dev/foo とラベル付けした場合、未定義の動作になります。SELinux の場合、これはラベル付けの競合になります。デバイスノードには 1 つのラベルしか付けられないため、最後に適用されたラベルが有効になります。その結果、次のような状況が発生します。

  • 適用に失敗したラベルへのアクセスを必要とするプロセスは、リソースにアクセスできなくなります。
  • ファイルへのアクセスを得たプロセスは、間違ったデバイスノードが作成されたことで、中断される可能性があります。

システム プロパティでも名前の競合が発生し、システムで(または SELinux のラベル付けで)未定義の動作が発生する可能性があります。プロパティ、サービス、プロセス、ファイル、ソケットなど、SELinux ラベルが付けられたオブジェクトでは、プラットフォームとベンダーのラベルの競合が発生する場合があります。こうした問題を回避するには、オブジェクトのオーナーシップを明確に定義してください。

ラベルの競合に加えて、SELinux のタイプ名または属性名が競合する場合もあります。タイプ名 / 属性名が競合すると、ポリシー コンパイラ エラーが必ず発生します。

タイプ / 属性の名前空間

SELinux では、同じタイプ / 属性を複数宣言することはできません。宣言が重複するポリシーはコンパイルに失敗します。タイプ名と属性名の競合を回避するには、ベンダーのすべての宣言で名前空間を np_ で開始する必要があります。

type foo, domain; → type np_foo, domain;

システム プロパティとプロセスのラベルのオーナーシップ

ラベルの競合を回避するには、プロパティ名前空間を使用するのが最適です。エクスポートされたプラットフォームのプロパティの名前を変更したり、追加したりする場合に、プラットフォームのプロパティを簡単に識別し、名前の競合を回避するには、すべてのベンダーのプロパティに独自のプレフィックスを付けるようにします。

プロパティのタイプ 使用できるプレフィックス
読み取り / 書き込み可能 vendor.
読み取り専用 ro.vendor.
ro.boot.
ro.hardware.
永続 persist.vendor.

ベンダーは引き続き、ro.boot.*(カーネル cmdline から得られる)と ro.hardware.*(明確なハードウェア関連プロパティ)を使用できます。

init rc ファイルのすべてのベンダー サービスでは、非システム パーティションの init rc ファイルのサービス用に、vendor. が必要です。同様のルールが、ベンダー プロパティの SELinux ラベルに適用されます(ベンダー プロパティでは vendor_)。

ファイルのオーナーシップ

プラットフォーム ポリシーとベンダー ポリシーは、どちらも共通してすべてのファイルシステムにラベルを付けるため、ファイルの競合を防止することは容易ではありません。タイプの名前付けとは異なり、ファイルの名前空間を指定することは、多くがカーネルによって作成されるため、現実的ではありません。競合を回避するには、このセクションに示す、ファイルシステムの名前付けに関するガイダンスに従ってください。Android 8.0 の場合、ガイダンスは技術的に必須ではなく、推奨事項になります。将来的に、こうした推奨事項はベンダー テストスイート(VTS)によって適用されるようになります。

システム(/system)

システム イメージでのみ、file_contextsservice_contexts などを使用して、/system コンポーネントにラベルを付ける必要があります。/vendor ポリシーで /system コンポーネントにラベルを追加してしまうと、フレームワークのみの OTA 更新はできない可能性があります。

ベンダー(/vendor)

AOSP SELinux ポリシーは、プラットフォームが接点を持つ vendor パーティションの各部のラベル付けをすでにしているため、プラットフォーム プロセス用の SELinux ルールを作成すれば、vendor パーティションの各部に対してやり取り、またはアクセスできます。例:

/vendor パス プラットフォーム提供のラベル ラベルに依存するプラットフォーム プロセス
/vendor(/.*)? vendor_file フレームワークのすべての HAL クライアント(ueventd など)
/vendor/framework(/.*)? vendor_framework_file dex2oatappdomain など
/vendor/app(/.*)? vendor_app_file dex2oatinstalldidmap など
/vendor/overlay(/.*) vendor_overlay_file system_serverzygoteidmap など

この結果、vendor パーティションで追加ファイルにラベルを付ける場合は、特定のルール(neverallows を通じて適用)に従う必要があります。

  • vendor パーティション内では、すべてのファイルに対して vendor_file をデフォルトのラベルにする必要があります。これは、プラットフォーム ポリシーがパススルー HAL の実装にアクセスするために必要です。
  • ベンダーの SEPolicy によって vendor パーティションに追加されたすべての新しい exec_types では、vendor_file_type 属性が必要です。これは neverallow によって適用されます。
  • 将来のプラットフォームまたはフレームワークの更新で競合を回避するには、vendor パーティションでファイルに exec_types 以外のラベルを付けないようにしてください。
  • AOSP で識別される同じプロセス HAL のすべてのライブラリ依存関係には、same_process_hal_file. としてラベル付けする必要があります。

Procfs(/proc)

/proc 内のファイルには、genfscon ラベルのみでラベル付けできます。Android 7.0 では、プラットフォーム ポリシーとベンダー ポリシーの両方で、procfs 内のファイルのラベル付けに genfscon が使用されています。

おすすめの方法: プラットフォーム ポリシーでのみ /proc でラベル付けします。vendor プロセスが、デフォルトのラベル(proc)が付与されている /proc 内のファイルにアクセスする必要がある場合は、ベンダー ポリシーでは明示的にラベル付けせず、汎用的な proc タイプを使用してベンダー ドメインのルールを追加してください。こうすることで、プラットフォームを更新しても、procfs によって公開される将来のカーネル インターフェースに対応でき、必要に応じてそれらに明示的にラベル付けできるようになります。

Debugfs(/sys/kernel/debug)

Debugfs には、file_contextsgenfscon の両方でラベル付けできます。Android 7.0 では、プラットフォームとベンダーの両方で debugfs をラベル付けします。

おすすめの方法: 短期的には、ベンダー ポリシーでのみ debugfs をラベル付けします。長期にわたる場合は、debugfs を削除します。

Tracefs(/sys/kernel/debug/tracing)

Tracefs には、file_contextsgenfscon の両方でラベル付けできます。Android 7.0 では、プラットフォームのみで tracefs をラベル付けします。

おすすめの方法: プラットフォームのみで tracefs をラベル付けします。

Sysfs(/sys)

/sys 内のファイルには、file_contextsgenfscon の両方を使用してラベル付けできます。Android 7.0 では、プラットフォームとベンダーの両方が、sysfs 内のファイルのラベル付けに file_contextsgenfscon を使用しています。

おすすめの方法: プラットフォームでは、デバイス固有でない sysfs ノードにラベル付けできます。それ以外の場合、ファイルにラベル付けできるのはベンダーだけです。

tmpfs(/dev)

/dev 内のファイルは file_contexts でラベル付けできます。Android 7.0 では、プラットフォームとベンダーの両方が、ここでファイルにラベル付けします。

おすすめの方法: ベンダーは、/dev/vendor 内のファイルにのみラベル付けできます(/dev/vendor/foo/dev/vendor/socket/bar など)。

Rootfs(/)

/ 内のファイルは file_contexts でラベル付けできます。Android 7.0 では、プラットフォームとベンダーの両方がここでファイルにラベル付けします。

おすすめの方法: / 内のファイルにはシステムのみがラベル付けできます。

データ(/data)

データには、file_contextsseapp_contexts を組み合わせてラベル付けします。

おすすめの方法: ベンダーが /data/vendor 以外でラベル付けできないようにします。/data の他の部分にラベル付けできるのはプラットフォームだけです。

互換性属性

SELinux ポリシーは、特定のオブジェクト クラスと権限のための、ソースタイプとターゲット タイプ間のインタラクションです。SELinux ポリシーの影響を受けるすべてのオブジェクト(プロセス、ファイルなど)は、タイプが 1 つだけであっても、そのタイプに複数の属性がある場合があります。

ポリシーはほとんどの場合、既存のタイプに基づいて記述されています。

allow source_type target_type:target_class permission(s);

これが機能するのは、すべてのタイプを把握している状態でポリシーが記述されているためです。ただし、ベンダー ポリシーとプラットフォーム ポリシーで特定のタイプが使用されている場合に、特定のオブジェクトのラベルがいずれか 1 つのポリシーだけで変更されてしまうと、もう一方では、以前に依存していたアクセス権を得たり、あるいは喪失したりするポリシーがでてくる可能性があります。たとえば:

File_contexts:
    /sys/A   u:object_r:sysfs:s0
    Platform: allow p_domain sysfs:class perm;
    Vendor: allow v_domain sysfs:class perm;

上記が次のように変更されたとします。

File_contexts:
    /sys/A   u:object_r:sysfs_A:s0

ベンダー ポリシーは同じままであっても、新しい sysfs_A タイプに対応するポリシーがないため、v_domain はアクセスを失います。

属性に基づいてポリシーを定義することで、基盤となるオブジェクトに、プラットフォームとベンダーコードの両方のポリシーに対応する属性を持つタイプを付与できるようになります。これをすべてのタイプで行うことで、コンクリート タイプが使用されることのない、属性に基づくポリシーを効果的に作成できます。これは実際には、ポリシーの中でプラットフォームとベンダーの両方に適用される部分でのみ必要になります。これは、ベンダー ポリシーの一部として作成されるプラットフォーム パブリック ポリシーとして定義され適用されます。

バージョニングされた属性としてパブリック ポリシーを定義することで、ポリシーの互換性に関する 2 つの目標が達成されます。

  • プラットフォームの更新後もベンダーコードが機能し続けること。ベンダーコードが依存していたオブジェクトに対応するオブジェクトのコンクリート タイプに属性を追加し、アクセスを保持することで達成されます。
  • ポリシーのサポートを終了できること。ポリシーセットを属性によって明確に区分し、その属性が対応しているバージョンのサポートが終了した時点で削除できるようにすることで達成されます。ベンダー ポリシーにまだ古いポリシーが含まれていても、アップグレードされた時点で自動的に削除されることがわかるので、プラットフォームでの開発を続行できます。

ポリシーの記述可能性

個々のバージョン変更について把握していなくてもポリシー開発が行えるように、Android 8.0 では、プラットフォーム パブリック ポリシータイプとそれらの属性とのマッピングが行われます。タイプ foo は属性 foo_vN にマッピングされ、N はターゲットとなるバージョンです。vNPLATFORM_SEPOLICY_VERSION ビルド変数に対応するもので、形式は MM.NN です。MM はプラットフォーム SDK 番号に対応し、NN はプラットフォーム sepolicy 固有のバージョンです。

パブリック ポリシーの属性はバージョニングされず、API として存在します。この API に基づいてプラットフォーム ポリシーとベンダー ポリシーを構築し、2 つのパーティション間のインターフェースの安定性を維持できます。プラットフォーム ポリシーとベンダー ポリシーのライターは、それが現在作成されたものであるかのように、ポリシーの作成を続行できます。

allow source_foo target_bar:class perm; としてエクスポートされるプラットフォーム パブリック ポリシーは、ベンダー ポリシーの一部として含まれます。コンピレーション(対応するバージョンを含む)中に、デバイスのベンダー部分に適用されるポリシー(変換された Common Intermediate Language(CIL)で示される)に変換されます。

 (allow source_foo_vN target_bar_vN (class (perm)))

ベンダー ポリシーはプラットフォームに先行することがないため、以前のバージョンを考慮する必要はありません。ただしプラットフォーム ポリシーは、ベンダー ポリシーがどの時点のものであるかを把握し、そのタイプの属性を含め、バージョニングされた属性に対応するポリシーを設定する必要があります。

ポリシーの相違

各タイプの末尾に _vN を追加して属性を自動的に作成しても、異なるバージョン間でタイプに属性をマッピングできなければ効果がありません。Android では、属性のバージョン間のマッピングと、それらの属性に対するタイプのマッピングが維持されます。これは前述のマッピング ファイルとステートメント(CIL など)によって行われます。

(typeattributeset foo_vN (foo))

プラットフォームのアップグレード

このセクションでは、プラットフォームのアップグレード シナリオを詳細に示します。

同じタイプ

このシナリオは、ポリシーのバージョン間でオブジェクトのラベルが変更されない場合に該当します。これはソースとターゲットのタイプでも同じで、/dev/binder でも見られます。ここでは、すべてのリリースについて binder_device とラベル付けされています。変換されたポリシーでは次のようになります。

binder_device_v1 … binder_device_vN

v1 から v2 にアップグレードする場合、プラットフォーム ポリシーには次のものを含める必要があります。

type binder_device; -> (type binder_device) (in CIL)

v1 マッピング ファイル(CIL)内:

(typeattributeset binder_device_v1 (binder_device))

v2 マッピング ファイル(CIL)内:

(typeattributeset binder_device_v2 (binder_device))

v1 ベンダー ポリシー(CIL)内:

(typeattribute binder_device_v1)
    (allow binder_device_v1 …)

v2 ベンダー ポリシー(CIL)内:

(typeattribute binder_device_v2)
    (allow binder_device_v2 …)
新しいタイプ

このシナリオは、プラットフォームに新しいタイプが追加される場合に該当します。新しいタイプを追加するのは、新機能を追加するときやポリシーを強化するときなどです。

  • 新しい機能。それまで存在しなかったオブジェクト(新しいサービス プロセスなど)にラベル付けするタイプの場合、それまでベンダーコードはそのオブジェクトを直接操作していなかったので、対応するポリシーが存在しません。このタイプに対応する新しい属性には、前のバージョンの属性がないため、そのバージョンをターゲットとするマッピング ファイルでエントリは不要です。
  • ポリシーの強化。タイプがポリシーの強化を表している場合、新しいタイプの属性は、以前の属性に対応する属性のチェーンにリンクバックしている必要があります(/sys/Asysfs から sysfs_A に変更した前述の例と同様)。ベンダーコードは sysfs へのアクセスを可能にするルールに依存しているため、そのルールを新しいタイプの属性として含める必要があります。

v1 から v2 にアップグレードする場合、プラットフォーム ポリシーには次のものを含める必要があります。

type sysfs_A; -> (type sysfs_A) (in CIL)
    type sysfs; (type sysfs) (in CIL)

v1 マッピング ファイル(CIL)内:

(typeattributeset sysfs_v1 (sysfs sysfs_A))

v2 マッピング ファイル(CIL)内:

(typeattributeset sysfs_v2 (sysfs))
    (typeattributeset sysfs_A_v2 (sysfs_A))

v1 ベンダー ポリシー(CIL)内:

(typeattribute sysfs_v1)
    (allow … sysfs_v1 …)

v2 ベンダー ポリシー(CIL)内:

(typeattribute sysfs_A_v2)
    (allow … sysfs_A_v2 …)
    (typeattribute sysfs_v2)
    (allow … sysfs_v2 …)
削除されたタイプ

まれに発生するこのシナリオは、基盤となるオブジェクトが次の状態になり、タイプが削除されることで発生します。

  • そのまま残るが別のラベルが付けられる。
  • プラットフォームから削除される。

ポリシーの緩和を行うとき、タイプが削除され、そのタイプでラベル付けされていたオブジェクトには、別の既存のラベルが付けられます。これは属性のマッピングの統合を意味します。ベンダーコードは、それまでに持っていた属性によって、引き続き基盤となるオブジェクトにアクセスできなければなりませんが、システムのその他の部分は統合後、新しい属性によって基盤となるオブジェクトにアクセスできる必要があります。

切り替えた属性が新しい場合、ラベルの変更は新しいタイプのケースと同様です。ただし、既存のラベルが使用されている場合、古い属性を新しいタイプに追加すると、そのタイプでラベル付けされている他のオブジェクトも、新たにアクセス可能になってしまいます。これは基本的にプラットフォームで行われていることであり、互換性を維持するための妥当なトレードオフであるとされています。

(typeattribute sysfs_v1)
    (allow … sysfs_v1 …)

サンプル バージョン 1: タイプの廃止(sysfs_A の削除)

v1 から v2 にアップグレードする場合、プラットフォーム ポリシーには次のものを含める必要があります。

type sysfs; (type sysfs) (in CIL)

v1 マッピング ファイル(CIL)内:

(typeattributeset sysfs_v1 (sysfs))
    (type sysfs_A) # in case vendors used the sysfs_A label on objects
    (typeattributeset sysfs_A_v1 (sysfs sysfs_A))

v2 マッピング ファイル(CIL)内:

(typeattributeset sysfs_v2 (sysfs))

v1 ベンダー ポリシー(CIL)内:

(typeattribute sysfs_A_v1)
    (allow … sysfs_A_v1 …)
    (typeattribute sysfs_v1)
    (allow … sysfs_v1 …)

v2 ベンダー ポリシー(CIL)内:

(typeattribute sysfs_v2)
    (allow … sysfs_v2 …)

サンプル バージョン 2: 完全に削除(foo タイプ)

v1 から v2 にアップグレードする場合、プラットフォーム ポリシーには次のものを含める必要があります。

# nothing - we got rid of the type

v1 マッピング ファイル(CIL)内:

(type foo) #needed in case vendors used the foo label on objects
    (typeattributeset foo_v1 (foo))

v2 マッピング ファイル(CIL)内:

# nothing - get rid of it

v1 ベンダー ポリシー(CIL)内:

(typeattribute foo_v1)
    (allow foo …)
    (typeattribute sysfs_v1)
    (allow sysfs_v1 …)

v2 ベンダー ポリシー(CIL)内:

(typeattribute sysfs_v2)
    (allow sysfs_v2 …)
新しいクラス / 権限

このシナリオは、プラットフォームのアップグレードによって、以前のバージョンでは存在しなかった新しいポリシー コンポーネントが導入された場合に該当します。たとえば、追加、検索、リスト権限を作成する servicemanager オブジェクト マネージャが Android によって追加された場合、servicemanager に登録しようとするベンダー デーモンは、利用できない権限を必要としました。Android 8.0 では、プラットフォーム ポリシーだけが新しいクラスと権限を追加できます。

ベンダー ポリシーによって作成または拡張されたすべてのドメインが、新しいクラスを自由に使用できるようにするには、プラットフォームに次のようなルールを含める必要があります。

allow {domain -coredomain} *:new_class perm;

これには、ベンダー イメージがアクセス権を取得できるように、すべてのインターフェース(パブリック ポリシー)タイプに対してアクセスを許可するポリシーが必要になる可能性があります。それによって許容できないセキュリティ ポリシー(servicemanager の変更の例のような)が作成されることになる場合は、ベンダーのアップグレードを強制的に行うこともあります。

クラス / 権限の削除

このシナリオは、オブジェクト マネージャ(ZygoteConnection オブジェクト マネージャなど)が削除されたときに問題が発生しないようにする場合に該当します。オブジェクト マネージャのクラスおよび権限は、そのベンダー バージョンによって使用されなくなるまで、ポリシーで定義されたままになる可能性があります。その場合は、対応するマッピング ファイルに定義を追加します。

新しいタイプまたはラベルが変更されたタイプに関するベンダーのカスタマイズ

新しいベンダータイプは、新しいプロセス、バイナリ、デバイス、サブシステム、保存データを記述するために必要であることから、ベンダー ポリシー開発の中核になっています。そのため、ベンダー定義のタイプの作成を許可することが不可欠です。

ベンダー ポリシーは常にデバイス上で最も古いポリシーであることから、すべてのベンダータイプをポリシー内の属性に自動的に変換する必要はありません。プラットフォームは、ベンダー ポリシーでラベル付けされているものを認識していないため、それらには依存しません。ただし、プラットフォームはパブリック タイプ(domainsysfs_type など)でラベル付けされているオブジェクトとのインタラクションに使用される属性とパブリック タイプを提供する必要があります。プラットフォームがこれらのオブジェクトとのインタラクションを正しく継続するには、属性とタイプを適切に適用し、カスタマイズ可能なドメイン(init など)に特定のルールを追加する必要があります。

Android 9 での属性の変更

Android 9 にアップグレードするデバイスでは、次の属性を使用できますが、Android 9 でリリースされているデバイスでは使用できません。

違反者属性

Android 9 には、次のようなドメイン関連の属性が含まれています。

  • data_between_core_and_vendor_violatorsvendorcoredomains 間のパスを通じてファイルを共有しない要件に違反したすべてのドメインに対する属性。プラットフォームとベンダー プロセスでは、ディスク上のファイルを使用して通信を行うべきではありません(不安定な ABI)。おすすめの方法:
    • ベンダーコードには /data/vendor を使用します。
    • システムでは /data/vendor を使用すべきではありません。
  • system_executes_vendor_violators。ベンダー バイナリを実行してはならないという要件に違反したすべてのシステム ドメイン(init および shell domains を除く)に対する属性。ベンダー バイナリを実行することは不安定な API の原因になります。プラットフォームでは、ベンダー バイナリを直接実行すべきではありません。おすすめの方法:
    • ベンダー バイナリに対するプラットフォームのそのような依存関係には、HIDL HAL が優先します。

      または

    • ベンダー バイナリへのアクセスを必要とする coredomains は、ベンダー パーティションに移動して、coredomain でなくする必要があります。

信頼できない属性

任意のコードをホストする信頼できないアプリは、HwBinder サービスにアクセスできるべきではありません。ただし、そのようなアプリが HwBinder サービスにアクセスしても十分に安全であると見なされる場合を除きます(以下の安全なサービスを参照)。これには、主な理由が 2 つあります。

  1. HIDL では呼び出し元の UID 情報を公開しないため、HwBinder サーバーはクライアント認証を実行しません。HIDL がそのようなデータを公開したとしても、多くの HwBinder サービスは、アプリより下のレベルで動作しているか(HAL など)、認証をアプリの ID に依存できません。したがって安全性を確保するために、すべての HwBinder サービスが、サービスが提供するオペレーションを実行する権限が同等に付与されているものとしてすべてのクライアントを扱うことがデフォルトで想定されています。
  2. HAL サーバー(HwBinder サービスのサブセット)には、system/core コンポーネントよりもセキュリティ上の問題の発生率が高いコードが含まれており、スタックの低位にある層に対するアクセス権(ハードウェアまでを含む)を持っています。そのため、Android のセキュリティ モデルがバイパスされる可能性が高まります。

安全なサービス

安全なサービスの例としては次のものが挙げられます。

  • same_process_hwservice。これらのサービスは(定義上)クライアントのプロセスで実行されるため、プロセスが実行されているクライアント ドメインと同じアクセス権が付与されています。
  • coredomain_hwservice。これらのサービスには、2 番目の理由に関連するリスクはありません。
  • hal_configstore_ISurfaceFlingerConfigs。このサービスは、どのドメインでも使用できるように特別に設計されています。
  • hal_graphics_allocator_hwservice。これらのオペレーションは、アプリがアクセスを許可されている surfaceflinger Binder サービスによって提供されています。
  • hal_omx_hwservice。これは、アプリがアクセスを許可されている mediacodec Binder サービスの HwBinder バージョンです。
  • hal_codec2_hwservice。これは hal_omx_hwservice の新しいバージョンです。

使用可能な属性

安全と見なされていないすべての hwservices には、属性 untrusted_app_visible_hwservice が与えられています。対応する HAL サーバーには属性 untrusted_app_visible_halserver が与えられています。Android P でリリースされているデバイスは、どの untrusted 属性も使用することはできません。

おすすめの方法:

  • 信頼できないアプリは、代わりにベンダー HIDL HAL と通信するシステム サービスと通信する必要があります。たとえば、アプリは binderservicedomainmediaserverbinderservicedomain)、さらに hal_graphics_allocator の順に通信できます。

    または

  • vendor HAL に直接アクセスする必要があるアプリは、独自のベンダー定義の sepolicy ドメインが必要です。

ファイル属性のテスト

Android 9 には、特定の場所にあるすべてのファイルに適切な属性が与えられている(sysfs内のすべてのファイルに必要な sysfs_type 属性が与えられているなど)ことを確認する、ビルド時テストが含まれています。

プラットフォーム パブリック ポリシー

プラットフォーム パブリック ポリシーは、Android 8.0 アーキテクチャ モデルに準拠するための中核となるものです。ここでは、v1 と v2 のプラットフォーム ポリシーの統一性をただ維持するというやり方はしません。ベンダーには、プラットフォーム ポリシーのサブセットが公開されます。このサブセットには、使用可能なタイプと属性、そしてそれらのタイプと属性に関するルールが含まれており、これはベンダー ポリシー(vendor_sepolicy.cil)の一部になります。

タイプとルールは、ベンダーが生成したポリシー内で自動的に attribute_vN に変換されます。これにより、プラットフォームが提供するタイプは、すべてバージョニングされた属性になります(ただし属性はバージョニングされません)。プラットフォームは、自身が提供するコンクリート タイプを適切な属性にマッピングする必要があります。これにより、ベンダー ポリシーは機能を継続でき、特定のバージョンについて提供されていたルールも含まれるようになります。プラットフォーム パブリックポリシーとベンダー ポリシーの組み合わせにより、独立プラットフォームとベンダービルドを許可する Android 8.0 アーキテクチャ モデルの目標が達成されます。

属性チェーンへのマッピング

ポリシー バージョンへのマッピングに属性を使用する場合、1 つのタイプは 1 つの属性または複数の属性にマッピングされます。こうすることで、そのタイプによってラベル付けされたオブジェクトに、以前のタイプに対応する属性を通じてアクセスできるようになります。

ポリシーの作成者にバージョン情報が見えないようにするという目標を維持するために、バージョニングされた属性が自動的に生成され、適切なタイプに割り当てられます。一般的な静的なタイプのケースでは、単純に type_footype_foo_v1 にマッピングされます。

sysfs から sysfs_Amediaserver から audioserver などのオブジェクト ラベルの変更については、このマッピングの作成が重要になります(以下の例を参照)。プラットフォーム ポリシーを維持するには、オブジェクトの移行ポイントでマッピングをどのように作成するかを決定する必要があります。これには、オブジェクトと割り当てられているラベルとの関係を把握することと、それがいつ行われるかを判断することが求められます。下位互換性を確保するには、uprev する可能性がある唯一のパーティションとなるプラットフォーム側で、この複雑性を管理する必要があります。

バージョンの uprev

Android プラットフォームでは、簡素化のために、新しいリリース ブランチがカットされる際に、sepolicy バージョンをリリースしています。上記のように、バージョン番号は PLATFORM_SEPOLICY_VERSION に含まれ、形式は MM.nn です。MM は SDK の値に対応し、nn /platform/system/sepolicy. で維持されるプライベート値です。たとえば Kitkat では 19.0、Lollipop では 21.0、Lollipop-MR1 では 22.0、Marshmallow では 23.0、Nougat では 24.0、Nougat-MR1 では 25.0、Oreo では 26.0、Oreo-MR1 では 27.0、Android P では 28.0 です。uprev は必ずしも整数であるとは限りません。たとえば、バージョンへの MR バンプによって system/sepolicy/public で互換性のない変更が必要になり、それが API バンプではない場合、その sepolicy バージョンは vN.1 になる場合があります。開発ブランチのバージョンは、リリースされるデバイスで使用されることがない 10000.0 です。

Android では、uprev の際に最も古いバージョンのサポートを終了する場合があります。Android では、バージョンのサポート終了の頃合いを判断するために、その Android バージョンを実行していて、まだプラットフォームのメジャー アップデートを受け取っているベンダー ポリシーがあるデバイスの数を収集する場合があります。特定のバージョンのデバイス数が特定のしきい値を下回った場合、そのバージョンのサポートが終了します。

複数の属性によるパフォーマンス上の影響

https://github.com/SELinuxProject/cil/issues/9 に示すように、1 つのタイプに多数の属性を割り当てると、ポリシーのキャッシュミスが発生した場合にパフォーマンス上の問題が発生します。

これは Android で問題として確認されているため、Android 8.0 では変更が行われ、ポリシー コンパイラによって追加された属性と、使用されていない属性が削除されました。これらの変更により、パフォーマンス低下の問題が解決されました。

SELinux コンテキストのラベル付け

プラットフォームとベンダーの sepolicy を区別しやすくするために、システムでは SELinux コンテキスト ファイルをそれぞれ異なる方法でビルドして、ファイルを分離しています。

ファイルのコンテキスト

Android 8.0 では、file_contexts について次のような変更が行われています。

  • デバイスの起動時に追加のコンパイルによるオーバーヘッドを回避するために、バイナリ形式では file_contexts がなくなっています。代わりに {property, service}_contexts のような読み取り可能な正規表現のテキスト ファイルが使用されます(7.0 以前と同様)。
  • file_contexts は 2 つのファイルに分割されます。
    • plat_file_contexts
      • /vendor パーティションのラベル部分を除いてデバイス固有のラベルがない Android プラットフォーム file_context。このパーティションに正確にラベル付けして、sepolicy ファイルの適切な機能を確保する必要があります。
      • デバイスの /system/etc/selinux/plat_file_contexts にある system パーティションに存在し、起動時にベンダー file_context と合わせて init によって読み込む必要があります。
    • vendor_file_contexts
      • デバイスの Boardconfig.mk ファイルの BOARD_SEPOLICY_DIRS で指定されたディレクトリにある file_contexts を組み合わせることで構築される、デバイス固有の file_context
      • vendor パーティションの /vendor/etc/selinux/vendor_file_contexts にインストールし、起動時にプラットフォーム file_context と合わせて、init によって読み込む必要があります。

プロパティのコンテキスト

Android 8.0 では、property_contexts が 2 つのファイルに分割されています。

  • plat_property_contexts
    • デバイス固有のラベルがない、Android プラットフォーム property_context
    • /system/etc/selinux/plat_property_contextssystem パーティションに存在し、起動時にベンダーの property_contexts と合わせて、init によって読み込む必要があります。
  • vendor_property_contexts
    • デバイスの Boardconfig.mk ファイルの BOARD_SEPOLICY_DIRS で指定されたディレクトリにある property_contexts を組み合わせることで構築される、デバイス固有の property_context
    • /vendor/etc/selinux/vendor_property_contextsvendor パーティションに存在し、起動時にプラットフォーム property_context と合わせて、init によって読み込む必要があります。

サービスのコンテキスト

Android 8.0 では、service_contexts が次の 2 つのファイルに分割されています。

  • plat_service_contexts
    • servicemanager のための Android プラットフォーム固有の service_contextservice_context にはデバイス固有のラベルがありません。
    • /system/etc/selinux/plat_service_contextssystem のパーティションに存在し、起動時にベンダー service_contexts と合わせて、servicemanager によって読み込む必要があります。
  • vendor_service_contexts
    • デバイスの Boardconfig.mk ファイルの BOARD_SEPOLICY_DIRS で指定されたディレクトリにある service_contexts を組み合わせることで構築される、デバイス固有の service_context
    • /vendor/etc/selinux/vendor_service_contextsvendor パーティションに存在し、起動時にプラットフォームの service_contexts と合わせて、servicemanager によって読み込む必要があります。
    • servicemanager は起動時にこのファイルを検索しますが、TREBLE デバイスのコンプライアンスを確保するには、vendor_service_contexts が存在してはなりません。これは、vendor プロセスと system プロセス間のすべてのインタラクションに、hwservicemanager/hwbinder を適用する必要があるためです。
  • plat_hwservice_contexts
    • デバイス固有のラベルがない hwservicemanager 用の Android プラットフォーム hwservice_context
    • /system/etc/selinux/plat_hwservice_contextssystem のパーティションに存在し、起動時に vendor_hwservice_contexts と合わせて、hwservicemanager によって読み込む必要があります。
  • vendor_hwservice_contexts
    • デバイスの Boardconfig.mk ファイルの BOARD_SEPOLICY_DIRS で指定されたディレクトリにある hwservice_contexts を組み合わせることで構築される、デバイス固有の hwservice_context
    • /vendor/etc/selinux/vendor_hwservice_contextsvendor パーティションに存在し、起動時に plat_service_contexts と合わせて、hwservicemanager によって読み込む必要があります。
  • vndservice_contexts
    • デバイスの Boardconfig.mk ファイルの BOARD_SEPOLICY_DIRS で指定されたディレクトリにある vndservice_contexts を組み合わせることで構築される vndservicemanager 用のデバイス固有の service_context
    • このファイルは /vendor/etc/selinux/vndservice_contextsvendor パーティションに存在し、起動時に vndservicemanager によって読み込む必要があります。

Seapp のコンテキスト

Android 8.0 では、seapp_contexts が 2 つのファイルに分割されています。

  • plat_seapp_contexts
    • デバイス固有の変更がない、Android プラットフォーム seapp_context
    • /system/etc/selinux/plat_seapp_contexts.system パーティションに存在する必要があります。
  • vendor_seapp_contexts
    • デバイスの Boardconfig.mk ファイルの BOARD_SEPOLICY_DIRS で指定されたディレクトリにある seapp_contexts を組み合わせることで構築される、プラットフォーム seapp_context のデバイス固有の拡張機能。
    • /vendor/etc/selinux/vendor_seapp_contextsvendor パーティションに存在する必要があります。

MAC 権限

Android 8.0 では、mac_permissions.xml が 2 つのファイルに分割されています。

  • プラットフォーム mac_permissions.xml
    • デバイス固有の変更がない、Android プラットフォーム mac_permissions.xml
    • /system/etc/selinux/.system パーティションに存在する必要があります。
  • プラットフォーム以外の mac_permissions.xml
    • デバイスの Boardconfig.mk ファイルの BOARD_SEPOLICY_DIRS で指定されたディレクトリにある mac_permissions.xml から構築される、プラットフォーム mac_permissions.xml のデバイス固有の拡張機能。
    • /vendor/etc/selinux/.vendor パーティションに存在する必要があります。