この記事では、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 では、同じタイプ / 属性を複数宣言することはできません。宣言が重複するポリシーはコンパイルに失敗します。タイプ名と属性名の競合を回避するには、ベンダーのすべての宣言で名前空間を vendor_
で開始する必要があります。
type foo, domain; → type vendor_foo, domain;
システム プロパティとプロセスのラベル付けのオーナーシップ
ラベルの競合を回避するには、プロパティ名前空間を使用するのが最適です。エクスポートされたプラットフォームのプロパティの名前変更または追加を行う場合に、プラットフォームのプロパティを簡単に識別して名前の競合を回避できるようにするには、すべてのベンダー プロパティに固有のプレフィックスを付けます。
プロパティのタイプ | 使用できるプレフィックス |
---|---|
制御プロパティ | ctl.vendor. ctl.start$vendor. ctl.stop$vendor. init.svc.vendor.
|
読み取り / 書き込み可能 | 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_contexts
や service_contexts
などを使用して、/system
コンポーネントにラベルを付ける必要があります。/vendor
ポリシーで /system
コンポーネントにラベルを追加すると、フレームワークのみの OTA アップデートができなくなる可能性があります。
ベンダー(/vendor)
AOSP SELinux ポリシーは、プラットフォームが操作する vendor
パーティションの各領域にすでにラベルを付けているため、プラットフォーム プロセス用の SELinux ルールを作成すれば、vendor
パーティションの各領域に対する通信またはアクセスが可能になります。例:
/vendor パス |
プラットフォーム提供のラベル | ラベルに依存するプラットフォーム プロセス |
---|---|---|
/vendor(/.*)?
|
vendor_file
|
フレームワークのすべての HAL クライアント(ueventd など)
|
/vendor/framework(/.*)?
|
vendor_framework_file
|
dex2oat 、appdomain など
|
/vendor/app(/.*)?
|
vendor_app_file
|
dex2oat 、installd 、idmap など
|
/vendor/overlay(/.*)
|
vendor_overlay_file
|
system_server 、zygote 、idmap など
|
この結果、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_contexts
と genfscon
の両方でラベル付けできます。Android 7.0 から Android 10 までは、プラットフォームとベンダーの両方で debugfs
というラベルを付けます。
Android 11 では、製品版デバイスで debugfs
にアクセスしたりマウントしたりすることはできません。デバイス メーカーは debugfs
を削除する必要があります。
Tracefs(/sys/kernel/debug/tracing)
Tracefs
には、file_contexts
と genfscon
の両方でラベル付けできます。Android 7.0 では、プラットフォームのみで tracefs
をラベル付けします。
おすすめの方法: プラットフォームのみで tracefs
をラベル付けします。
Sysfs(/sys)
/sys
内のファイルには、file_contexts
と genfscon
の両方でラベル付けできます。Android 7.0 では、プラットフォームとベンダーの両方で、sysfs
内のファイルのラベル付けに file_contexts
と genfscon
を使用します。
おすすめの方法: プラットフォームでは、デバイス固有でない 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_contexts
と seapp_contexts
を組み合わせてラベル付けします。
おすすめの方法: ベンダーが /data/vendor
以外でラベル付けすることを禁止します。プラットフォームだけで /data
の他の領域にラベル付けします。
互換性属性
SELinux ポリシーは、特定のオブジェクト クラスと権限のための、ソースタイプとターゲット タイプ間のインタラクションです。SELinux ポリシーの影響を受けるすべてのオブジェクト(プロセス、ファイルなど)のタイプが 1 つだけであっても、そのタイプに複数の属性が存在することがあります。
ポリシーは、ほとんどの場合、既存のタイプに基づいて記述されています。
allow source_type target_type:target_class permission(s);
これが機能するのは、すべてのタイプを把握している状態でポリシーが記述されているためです。ただし、ベンダー ポリシーとプラットフォーム ポリシーの両方で特定のタイプが使用されている場合、特定のオブジェクトのラベルが一方のポリシーだけで変更されると、もう一方のポリシーで、前に依存していたアクセス権を獲得または喪失するポリシーが発生する可能性があります。次に例を示します。
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
はターゲットとなるバージョンです。vN
は PLATFORM_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/A
をsysfs
から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
オブジェクト マネージャーなど)が削除されたときに問題が発生しないようにする場合に該当します。オブジェクト マネージャーのクラスと権限は、そのベンダー バージョンによって使用されなくなるまで、ポリシーで定義されたままにすることができます。そのためには、対応するマッピング ファイルに定義を追加します。
新しいタイプまたはラベルが変更されたタイプに関するベンダーのカスタマイズ
新しいベンダータイプは、新しいプロセス、バイナリ、デバイス、サブシステム、保存データを記述するために必要であることから、ベンダー ポリシー開発の中核になっています。そのため、ベンダーが定義するタイプの作成を許可することが不可欠です。
ベンダー ポリシーは常にデバイス上で最も古いポリシーであることから、すべてのベンダータイプをポリシー内の属性に自動的に変換する必要はありません。プラットフォームは、ベンダー ポリシーでラベル付けされているものを認識しないので、それらに依存しません。ただし、プラットフォームは、パブリック タイプ(domain
、sysfs_type
など)でラベル付けされているオブジェクトの操作に使用される属性とパブリック タイプを提供する必要があります。プラットフォームがこれらのオブジェクトを正しく操作し続けるには、属性とタイプを適切に適用し、カスタマイズ可能なドメイン(init
など)に特定のルールを追加する必要があります。
Android 9 での属性の変更
Android 9 にアップグレードするデバイスでは次の属性を使用できますが、Android 9 でリリースされるデバイスでは使用できません。
違反者属性
Android 9 には、次のようなドメイン関連の属性が含まれています。
data_between_core_and_vendor_violators
。vendor
とcoredomains
間のパスを通じてファイルを共有しないという要件に違反するすべてのドメインの属性。プラットフォーム プロセスとベンダー プロセスは、ディスク上のファイルを使用して通信するべきではありません(不安定な ABI)。おすすめの方法:- ベンダーコードでは
/data/vendor
を使用します。 - システムでは
/data/vendor
を使用しません。
- ベンダーコードでは
system_executes_vendor_violators
。ベンダー バイナリを実行しないという要件に違反するすべてのシステム ドメイン(init
とshell domains
を除く)の属性。ベンダー バイナリを実行することは不安定な API の原因になります。プラットフォームでは、ベンダー バイナリを直接実行すべきではありません。おすすめの方法:- ベンダー バイナリに対するプラットフォームのそのような依存関係には、HIDL HAL が優先します。
または
- ベンダー バイナリへのアクセスを必要とする
coredomains
は、ベンダー パーティションに移動することにより、coredomain
ではなくなります。
- ベンダー バイナリに対するプラットフォームのそのような依存関係には、HIDL HAL が優先します。
信頼できない属性
任意のコードをホストする信頼できないアプリは、HwBinder サービスにアクセスするべきではありません。ただし、そのようなアプリによるアクセスが十分に安全であると見なされる場合は別です(下記の安全なサービスを参照)。これには、主に 2 つの理由があります。
- 現在 HIDL は呼び出し元の UID 情報を公開していないため、HwBinder サーバーはクライアント認証を行いません。HIDL がそうしたデータを公開したとしても、多くの HwBinder サービスは、アプリより下のレベル(HAL など)で動作しているか、認証についてアプリの ID に依存してはならないかのいずれかです。したがって、安全性を確保するために、すべての HwBinder サービスは、すべてのクライアントを、サービスによって提供されるオペレーションを実行する権限を同等に付与されているものとして扱うとデフォルトで想定されています。
- 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 9 でリリースされるデバイスでは、どちらの untrusted
属性も使用しないでください。
おすすめの方法:
- 信頼できないアプリは、代替策として、ベンダー HIDL HAL と通信するシステム サービスと通信する必要があります。たとえば、アプリは
binderservicedomain
、mediaserver
(つまりbinderservicedomain
)、hal_graphics_allocator
と順に通信できます。または
vendor
HAL に直接アクセスする必要があるアプリには、独自のベンダー定義の sepolicy ドメインが必要です。
ファイル属性のテスト
Android 9 にはビルド時テストが含まれています。これにより、特定の場所にあるすべてのファイルに適切な属性が与えられている(たとえば、sysfs
内のすべてのファイルに必須の sysfs_type
属性が与えられている)ことを確認できます。
プラットフォーム パブリック ポリシー
プラットフォーム パブリック ポリシーは、単にプラットフォーム ポリシー v1 と v2 の融合を維持するのではなく、Android 8.0 アーキテクチャ モデルに準拠するための中核として機能します。ベンダーには、プラットフォーム ポリシーのサブセットが公開されます。このサブセットは、使用可能なタイプと属性、そしてそれらのタイプと属性に関するルールを含んでおり、これらはベンダー ポリシー(vendor_sepolicy.cil
)の一部になります。
タイプとルールは、ベンダーが生成したポリシー内で自動的に attribute_vN
に変換されます。これにより、プラットフォームが提供するタイプは、すべてバージョニングされた属性になります(ただし属性はバージョニングされません)。プラットフォームは、自身が提供するコンクリート タイプを適切な属性にマッピングする役割を果たします。これにより、ベンダー ポリシーが継続的に機能し、特定のバージョンについて提供されるルールが組み込まれます。プラットフォーム パブリックポリシーとベンダー ポリシーの組み合わせにより、独立したプラットフォーム ビルドとベンダービルドを可能にするという Android 8.0 アーキテクチャ モデルの目標が達成されます。
属性チェーンへのマッピング
ポリシー バージョンへのマッピングに属性を使用する場合、1 つのタイプは 1 つの属性または複数の属性にマッピングされます。これにより、そのタイプによってラベル付けされたオブジェクトに、以前のタイプに対応する属性を通じてアクセスできるようになります。
ポリシー作成者にバージョン情報が見えないようにするという目標を守るために、バージョニングされた属性が自動的に生成され、適切なタイプに割り当てられます。一般的な静的なタイプのケースでは、単純に type_foo
が type_foo_v1
にマッピングされます。
sysfs
→ sysfs_A
、mediaserver
→ 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 9 では 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 で変更が行われ、ポリシー コンパイラによってポリシーに追加された属性と、使用されていない属性が削除されました。これらの変更により、パフォーマンス低下の問題が解決されました。
system_ext と product のパブリック ポリシー
Android 11 以降、system_ext
パーティションと product
パーティションは、指定されたパブリック タイプをベンダー パーティションにエクスポートできます。プラットフォーム パブリック ポリシーと同様に、ベンダーはバージョニングされた属性に自動的に変換されるタイプとルールを使用します(例: type
から type_N
。N
はベンダー パーティションをビルドするプラットフォームのバージョン)。
system_ext
パーティションと product
パーティションが同じプラットフォーム バージョン N
に基づいている場合、ビルドシステムが system_ext/etc/selinux/mapping/N.cil
と product/etc/selinux/mapping/N.cil
へのベース マッピング ファイルを生成します。これらには、type
から type_N
への ID マッピングが含まれています。ベンダーは、バージョニングされた属性 type_N
を使用して type
にアクセスできます。
system_ext
パーティションと product
パーティションのみが更新された場合(例: N
から N+1
またはそれ以降に更新)、ベンダーは N
のままとなり、system_ext
パーティションと product
パーティションのタイプにアクセスできなくなります。このような破綻を防ぐために、system_ext
パーティションと product
パーティションでは、具体的なタイプから type_N
属性へのマッピング ファイルを用意する必要があります。N+1
(またはそれ以降)の system_ext
パーティションと product
パーティションで N
ベンダーをサポートする場合は、各パートナーでマッピング ファイルのメンテナンスを行ってください。
これを行うにあたり、パートナーには以下のことが求められます。
- 生成されたベース マッピング ファイルを
N
のsystem_ext
パーティションとproduct
パーティションからソースツリーにコピーすること。 - 必要に応じてマッピング ファイルを修正すること。
-
N+1
(またはそれ以降)のsystem_ext
パーティションとproduct
パーティションにマッピング ファイルをインストールすること。
たとえば、N
system_ext
に foo_type
という 1 つのパブリック タイプがあるとします。すると、N
system_ext
パーティションの system_ext/etc/selinux/mapping/N.cil
は次のようになります。
(typeattributeset foo_type_N (foo_type)) (expandtypeattribute foo_type_N true) (typeattribute foo_type_N)
bar_type
が N+1
system_ext に追加され、bar_type
を N
ベンダーの foo_type
にマッピングする必要がある場合は、N.cil
を
(typeattributeset foo_type_N (foo_type))
から
(typeattributeset foo_type_N (foo_type bar_type))
に変更してから、N+1
system_ext のパーティションにインストールします。N
ベンダーは、N+1
system_ext の foo_type
と bar_type
に引き続きアクセスできます。
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_contexts
のsystem
パーティションに配置し、起動時にベンダーのproperty_contexts
とともにinit
によって読み込む必要があります。
- デバイス固有のラベルがない、Android プラットフォームの
vendor_property_contexts
- デバイスの
Boardconfig.mk
ファイルのBOARD_SEPOLICY_DIRS
で指定されたディレクトリにあるproperty_contexts
を組み合わせることで構築される、デバイス固有のproperty_context
。 - このファイルは、
/vendor/etc/selinux/vendor_property_contexts
のvendor
パーティションに配置し、起動時にプラットフォームのproperty_context
とともにinit
によって読み込む必要があります。
- デバイスの
サービスのコンテキスト
Android 8.0 では、service_contexts
は次のファイルに分割されています。
plat_service_contexts
servicemanager
用の Android プラットフォーム固有のservice_context
。service_context
にはデバイス固有のラベルがありません。- このファイルは、
/system/etc/selinux/plat_service_contexts
のsystem
パーティションに配置し、起動時にベンダーのservice_contexts
とともにservicemanager
によって読み込む必要があります。
vendor_service_contexts
- デバイスの
Boardconfig.mk
ファイルのBOARD_SEPOLICY_DIRS
で指定されたディレクトリにあるservice_contexts
を組み合わせることで構築される、デバイス固有のservice_context
。 - このファイルは、
/vendor/etc/selinux/vendor_service_contexts
のvendor
パーティションに配置し、起動時にプラットフォームのservice_contexts
とともにservicemanager
によって読み込む必要があります。 servicemanager
は起動時にこのファイルを検索しますが、TREBLE
デバイスのコンプライアンスを完全に確保するには、vendor_service_contexts
が存在してはなりません。これは、vendor
プロセスとsystem
プロセス間のすべてのインタラクションがhwservicemanager
/hwbinder
を経由する必要があるためです。
- デバイスの
plat_hwservice_contexts
- デバイス固有のラベルがない
hwservicemanager
用の Android プラットフォームのhwservice_context
。 - このファイルは、
/system/etc/selinux/plat_hwservice_contexts
のsystem
パーティションに配置し、起動時にvendor_hwservice_contexts
とともにhwservicemanager
によって読み込む必要があります。
- デバイス固有のラベルがない
vendor_hwservice_contexts
- デバイスの
Boardconfig.mk
ファイルのBOARD_SEPOLICY_DIRS
で指定されたディレクトリにあるhwservice_contexts
を組み合わせることで構築される、デバイス固有のhwservice_context
。 - このファイルは、
/vendor/etc/selinux/vendor_hwservice_contexts
のvendor
パーティションに配置し、起動時にplat_service_contexts
とともにhwservicemanager
によって読み込む必要があります。
- デバイスの
vndservice_contexts
- デバイスの
Boardconfig.mk
ファイルのBOARD_SEPOLICY_DIRS
で指定されたディレクトリにあるvndservice_contexts
を組み合わせることで構築される、vndservicemanager
用のデバイス固有のservice_context
。 - このファイルは、
/vendor/etc/selinux/vndservice_contexts
のvendor
パーティションに配置し、起動時にvndservicemanager
によって読み込む必要があります。
- デバイスの
Seapp のコンテキスト
Android 8.0 では、seapp_contexts
は 2 つのファイルに分割されています。
plat_seapp_contexts
- デバイス固有の変更がない、Android プラットフォームの
seapp_context
。 - このファイルは、
/system/etc/selinux/plat_seapp_contexts.
のsystem
パーティションに配置する必要があります。
- デバイス固有の変更がない、Android プラットフォームの
vendor_seapp_contexts
- デバイスの
Boardconfig.mk
ファイルのBOARD_SEPOLICY_DIRS
で指定されたディレクトリにあるseapp_contexts
を組み合わせることで構築される、プラットフォームのseapp_context
のデバイス固有の拡張機能。 - このファイルは、
/vendor/etc/selinux/vendor_seapp_contexts
のvendor
パーティションに配置する必要があります。
- デバイスの
MAC 権限
Android 8.0 では、mac_permissions.xml
は 2 つのファイルに分割されています。
- プラットフォームの
mac_permissions.xml
- デバイス固有の変更がない、Android プラットフォームの
mac_permissions.xml
。 - このファイルは、
/system/etc/selinux/.
のsystem
パーティションに配置する必要があります。
- デバイス固有の変更がない、Android プラットフォームの
- プラットフォーム以外の
mac_permissions.xml
- デバイスの
Boardconfig.mk
ファイルのBOARD_SEPOLICY_DIRS
で指定されたディレクトリにあるmac_permissions.xml
から構築される、プラットフォームのmac_permissions.xml
のデバイス固有の拡張機能。 - このファイルは、
/vendor/etc/selinux/.
のvendor
パーティションに配置する必要があります。
- デバイスの