官方文档,写的很详细,方便不能的同学学习
https://source.android.google.cn/security/selinux/compatibility?hl=zh-cn
本文介绍 Android 如何处理与平台 OTA 相关的政策兼容性问题,其中新平台 SELinux 设置可能与旧供应商 SELinux 设置有所不同。
基于 Treble 的 SELinux 政策设计会考虑平台政策和供应商政策之间的二进制文件区别;如果供应商分区生成依赖项(例如 platform
< vendor
< oem
),则架构会变得更加复杂。
在 Android 8.0 及更高版本中,SELinux 全局政策划分为私有和公共组件。公共组件包含政策和相关基础架构,保证可用于平台版本。 此政策会向供应商政策编写者公开,让供应商编译的供应商政策文件在与平台提供的政策结合使用时,可以为设备产生功能齐全的政策。
Android 可维护平台政策中导出的具体类型与每个平台版本的相应版本化属性之间的映射。这可确保在使用类型标记对象时,不会破坏平台公共政策在之前版本中所保证的行为。系统通过使每个平台版本的映射文件保持最新来维护此映射,该映射文件会为公共政策中导出的每种类型保留属性成员资格信息。
在 Android 8.0 及更高版本中自定义政策时,必须为每个对象明确定义所有权,以使平台和供应商政策保持分离。例如,如果供应商标记 /dev/foo
而后平台在后续 OTA 中标记 /dev/foo
,则会出现未定义的行为。对于 SELinux,这表现为标签冲突。设备节点只能有一个标签,解析为最后应用的标签。因此:
系统属性也有可能存在命名冲突,进而导致系统上出现未定义行为(以及 SELinux 标签出现此行为)。具有 SELinux 标签的任何对象(包括属性、服务、进程、文件和套接字)都可能会出现平台和供应商标签冲突的情况。要避免此类问题,请明确定义这些对象的所有权。
除了标签冲突外,SELinux 类型/属性名称也可能出现冲突。 类型/属性名称冲突往往会导致政策编译器错误。
SELinux 不允许相同类型/属性的多个声明。具有重复声明的政策将无法编译。为避免类型和属性名称冲突,所有供应商声明都应是以 np_
开头的命名空间。
type foo, domain; → type np_foo, domain;
要避免标签冲突,最有效的解决方法是使用属性命名空间。要在重命名或添加导出的平台属性时轻松识别平台属性并避免名称冲突,请确保所有供应商属性都有各自的前缀:
属性类型 | 可接受的前缀 |
---|---|
可读写 | vendor. |
只读 | ro.vendor. ro.boot. ro.hardware. |
永久 | persist.vendor. |
供应商可以继续使用 ro.boot.*
(来自内核命令行)和 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 等 |
*有关更多示例,请参阅 system/sepolicy/private/file_contexts
。
因此,您在 vendor
分区中标记额外的文件时,必须遵循特定规则(通过 neverallows
强制执行):
vendor_file
必须是 vendor
分区中所有文件的默认标签。平台政策要求使用此标签来访问直通式 HAL 实现。vendor
分区中添加的所有新 exec_types
均必须具有 vendor_file_type
属性。这一规则将通过 neverallows 强制执行。vendor
分区中标记除 exec_types
之外的文件。same_process_hal_file.
Procfs (/proc)
/proc
中的文件可以仅使用 genfscon
标签进行标记。在 Android 7.0 中,平台政策和供应商政策都使用 genfscon
来标记 procfs
中的文件。
建议:只有平台政策可以标记 /proc
。如果 vendor
进程需要访问 /proc
中当前使用默认标签 (proc
) 标记的文件,则供应商政策不应明确标记它们,而应使用常规 proc
类型为供应商域添加规则。这样,平台更新可以适应通过 procfs
公开的未来内核接口,并根据需要进行明确标记。
Debugfs (/sys/kernel/debug)
Debugfs
可以在 file_contexts
和 genfscon
中进行标记。在 Android 7.0 中,平台和供应商都会标记 debugfs
。
建议:在短期内,只有供应商政策可以标记 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 中,平台和供应商都使用 file_contexts
和 genfscon
来标记 sysfs
中的文件。
建议:平台可以标记不针对特定设备的 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 政策影响的每个对象(进程、文件等)可能只有一种类型,但该类型可能有多个属性。
政策大多根据现有类型编写:
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
将失去访问权限。
通过根据属性定义政策,我们可以为底层对象提供一个类型,该类型具有与平台和供应商代码的政策相对应的属性。可以针对所有类型完成此操作,以便有效地创建一个其中从不使用具体类型的属性政策。实际上,只需对平台和供应商之间重叠的政策部分执行此操作,这些部分是作为平台公共政策(作为供应商政策的一部分进行编译)定义和提供的。
将公共政策定义为版本化属性可实现以下两个政策兼容性目标:
为了实现无需了解具体版本变化即可制定政策的目标,Android 8.0 包含平台公共政策类型与其属性之间的映射。类型 foo
映射到属性 foo_vN
,其中 N
是目标版本。vN
对应于 PLATFORM_SEPOLICY_VERSION
编译变量,格式为 MM.NN
(其中 MM
对应于平台 SDK 编号,NN
是平台 sepolicy 特定版本)。
公共政策中的属性未采用版本编号,而是以 API 形式存在(可以在上面构建平台和供应商政策,以使两个分区之间的接口保持稳定)。平台和供应商政策写入程序都可以像当前那样继续写入政策。
以 allow source_foo target_bar:class perm;
形式导出的平台公共政策包含在供应商政策中。在编译(包括相应的版本)期间,它将转换为将放入设备供应商部分的政策(以转换后的通用中间语言 (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 …)
新类/权限
当平台升级引入先前版本中不存在的新政策组件时,会出现这种情况。例如,当 Android 添加了创建添加、查找和列出权限的 servicemanager
对象管理器时,想要向 servicemanager
注册的供应商守护程序需要之前未提供的权限。在 Android 8.0 中,只有平台政策可以添加新的类和权限。
要允许所有可能由供应商政策创建或扩展的域毫无阻碍地使用新类,平台政策需要包含类似于下文的规则:
allow {domain -coredomain} *:new_class perm;
这甚至可能需要政策允许访问所有接口(公共政策)类型,以确保供应商映像获得访问权限。如果这会导致不可接受的安全政策(就像 servicemanager 更改可能会导致的结果一样),则系统可能会强制进行供应商升级。
移除的类/权限
移除对象管理器(例如 ZygoteConnection
对象管理器)会出现这种情况,应该不会导致出现问题。对象管理器类和权限可以一直在政策中保持已定义状态,直到供应商版本不再使用它为止。通过在相应的映射文件中添加定义,可以做到这一点。
新类型/重新添加标签的类型的供应商自定义
新供应商类型是制定供应商政策的核心,这是因为新供应商类型是说明新进程、二进制文件、设备、子系统和存储的数据所必需的。因此,必须允许创建供应商定义的类型。
由于供应商政策始终是设备上最旧的政策,因此无需自动将所有供应商类型转换为政策中的属性。平台不依赖于在供应商政策中标记的任何内容,因为平台并不知道它;但是,平台将提供它与带有这些类型标记的对象(例如 domain
、sysfs_type
等)进行交互所用的属性和公共类型。为使平台继续与这些对象正确交互,必须适当地应用这些属性和类型,并且可能需要将特定规则添加到可自定义域(例如 init
)中。
升级到 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。平台不应直接执行供应商二进制文件。建议:
或
coredomains
应移至供应商分区,因此不再是 coredomain
。托管任意代码的不受信任的应用不应具有 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
属性。
建议:
binderservicedomain
通信,然后 mediaserver
(属于 binderservicedomain
)再与 hal_graphics_allocator
通信。 或
vendor
HAL 的应用应具有各自的供应商定义的 sepolicy 域。Android 9 包含一些编译时测试,旨在确保特定位置的所有文件都具有适当的属性(例如,sysfs
中的所有文件都具有必需的 sysfs_type
属性)。
平台公共政策是遵循 Android 8.0 架构模型的核心所在,而不是简单地将 v1 和 v2 中的平台政策结合起来。供应商可以看到一部分平台政策(包含可用类型和属性以及关于这些类型和属性的规则),这部分政策随后会包含在供应商政策中(即 vendor_sepolicy.cil
)。
类型和规则会在供应商生成的政策中自动转换为 attribute_vN
,以便所有由平台提供的类型都是带有版本编号的属性(但属性不带版本编号)。平台负责将其提供的具体类型映射到适当的属性,以确保供应商政策继续有效,并将为特定版本提供的规则包括在内。将平台公共政策和供应商政策相结合可满足 Android 8.0 架构模型目标,即允许独立平台和供应商构建。
使用属性映射到政策版本时,一个类型会映射到一个或多个属性,确保使用该类型标记的对象可通过与这些对象之前的类型对应的属性访问。
达成向政策编写器隐藏版本信息的目标意味着自动生成版本化属性并分配给适当的类型。对于常见的静态类型,这很简单:type_foo
映射到 type_foo_v1
。
对于对象标签更改(例如 sysfs
→ sysfs_A
或 mediaserver
→ audioserver
),创建此映射非常重要(如上面的示例中所述)。平台政策维护者必须确定如何在对象的转换点处创建映射,这需要了解对象及其所分配到的标签之间的关系并确定何时发生这种情况。为了实现向后兼容性,需要在平台端(这是唯一可以升级的分区)管理这种复杂性。
为简单起见,Android 平台会在新版本分支发布后推出一个 sepolicy 版本。如上所述,版本号包含在 PLATFORM_SEPOLICY_VERSION
中,其格式为 MM.nn
,其中 MM
对应于 SDK 值,nn
是在 /platform/system/sepolicy.
中维护的不公开值。 例如,19.0
对应于 Kitkat,21.0
对应于 Lollipop,22.0
对应于 Lollipop-MR1,23.0
对应于 Marshmallow,24.0
对应于 Nougat,25.0
对应于 Nougat-MR1,26.0
对应于 Oreo,27.0
对应于 Oreo-MR1,28.0
对应于 Android P。Uprevs 不一定总是整数。例如,如果因 MR 版本递增而需要对 system/sepolicy/public
进行不兼容的更改,但不是 API 递增,则该 sepolicy 版本可以为 vN.1
。开发分支中的版本是 10000.0
,该版本绝不会用在搭载 Android 的设备中。
Android 可能会在升级时弃用最旧的版本。为了解何时弃用某个版本,Android 可能会根据供应商政策收集运行该 Android 版本且仍在接收主要平台更新的设备数量。如果该数字小于特定阈值,则会弃用该版本。
如 https://github.com/SELinuxProject/cil/issues/9 中所述,分配给某种类型的大量属性会在政策缓存未命中时导致性能问题。
这已被证实是 Android 中存在的问题,因此我们对 Android 8.0 进行了更改,以移除政策编译器添加到政策中的属性,另外还移除了未使用的属性。这些更改解决了性能降低问题。
为便于区别平台和供应商 sepolicy,系统以不同方式构建 SELinux 上下文文件以使它们分离开来。
Android 8.0 为 file_contexts
引入了以下更改:
file_contexts
不再以二进制文件形式存在,而是可读的正则表达式文本文件,例如 {property, service}_contexts
(和 7.0 之前的版本一样)。file_contexts
拆分为两个文件:
plat_file_contexts
file_context
(/vendor
分区的标签部分除外,为确保 sepolicy 文件正常运行必须为这些部分准确添加标签)。system
分区中的 /system/etc/selinux/plat_file_contexts
下,并由 init
在启动时加载(与供应商 file_context
一起加载)。vendor_file_contexts
file_context
,通过合并 file_contexts
(位于设备的 Boardconfig.mk
文件中由 BOARD_SEPOLICY_DIRS
指向的目录下)进行编译。vendor
分区的 /vendor/etc/selinux/vendor_file_contexts
中,并在启动时由 init
加载(与平台 file_context
一起加载)。在 Android 8.0 中,property_contexts
拆分到两个文件中:
plat_property_contexts
property_context
。system
分区中的 /system/etc/selinux/plat_property_contexts
下,并由 init
在启动时加载(与供应商 property_contexts
一起加载)。vendor_property_contexts
property_context
,通过合并 property_contexts
(位于设备的 Boardconfig.mk
文件中由 BOARD_SEPOLICY_DIRS
指向的目录下)进行编译。vendor
分区中的 /vendor/etc/selinux/vendor_property_contexts
下,并由 init
在启动时加载(与平台 property_context
一起加载)。在 Android 8.0 中,service_contexts
拆分到以下两个文件中:
plat_service_contexts
servicemanager
的 Android 平台特定 service_context
。service_context
没有设备特定标签。system
分区中的 /system/etc/selinux/plat_service_contexts
下,并由 servicemanager
在启动时加载(与供应商 service_contexts
一起加载)。vendor_service_contexts
service_context
,通过合并 service_contexts
(位于设备的 Boardconfig.mk
文件中由 BOARD_SEPOLICY_DIRS
指向的目录下)进行编译。vendor
分区中的 /vendor/etc/selinux/vendor_service_contexts
下,并由 servicemanager
在启动时加载(与平台 service_contexts
一起加载)。servicemanager
会在启动时查找此文件,但对于完全兼容的 TREBLE
设备,vendor_service_contexts
绝不能存在。这是因为 vendor
和 system
进程之间的所有交互都必须执行 hwservicemanager
/hwbinder
。plat_hwservice_contexts
hwservicemanager
的 Android 平台 hwservice_context
(没有任何设备特定标签)。system
分区中的 /system/etc/selinux/plat_hwservice_contexts
下,并由 hwservicemanager
在启动时加载(与 vendor_hwservice_contexts
一起加载)。vendor_hwservice_contexts
hwservice_context
,通过合并 hwservice_contexts
(位于设备的 Boardconfig.mk
文件中由 BOARD_SEPOLICY_DIRS
指向的目录下)进行编译。vendor
分区中的 /vendor/etc/selinux/vendor_hwservice_contexts
下,并由 hwservicemanager
在启动时加载(与 plat_service_contexts
一起加载)。vndservice_contexts
vndservicemanager
的设备特定 service_context
,通过合并 vndservice_contexts
(位于设备的 Boardconfig.mk
文件中由 BOARD_SEPOLICY_DIRS
指向的目录下)进行编译。vendor
分区中的 /vendor/etc/selinux/vndservice_contexts
下,并由 vndservicemanager
在启动时加载。在 Android 8.0 中,seapp_contexts
拆分到两个文件中:
plat_seapp_contexts
seapp_context
。system
分区中的 /system/etc/selinux/plat_seapp_contexts.
下。vendor_seapp_contexts
seapp_context
的设备特定扩展,通过合并 seapp_contexts
(位于设备的 Boardconfig.mk
文件中由 BOARD_SEPOLICY_DIRS
指向的目录下)进行编译。vendor
分区中的 /vendor/etc/selinux/vendor_seapp_contexts
下。在 Android 8.0 中,mac_permissions.xml
拆分到两个文件中:
mac_permissions.xml
mac_permissions.xml
。system
分区中的 /system/etc/selinux/.
下。mac_permissions.xml
mac_permissions.xml
的设备特定扩展,通过 mac_permissions.xml
(位于设备的 Boardconfig.mk
文件中由 BOARD_SEPOLICY_DIRS
指向的目录下)进行编译。vendor
分区中的 /vendor/etc/selinux/.
下。