Android SELinux介绍


1. 概述

SELinux 按照默认拒绝的原则运行:任何未经明确允许的行为都会被拒绝。SELinux 可按两种全局模式运行:

  • 宽容模式:权限拒绝事件会被记录下来,但不会被强制执行。
  • 强制模式:权限拒绝事件会被记录下来并强制执行。

2. 概念

2.1. 类型、属性和规则

Android 依靠 SELinux 的类型强制执行 (TE) 组件来实施其政策。这表示所有对象(例如文件、进程或套接字)都具有相关联的类型。例如,默认情况下,应用的类型为untrusted_app。对于进程而言,其类型也称为域。可以使用一个或多个属性为类型添加注解。属性可用于同时指代多种类型。 对象会映射到类(例如文件、目录、符号链接、套接字),并且每个类的不同访问权限类型由权限表示。例如,file类存在权限open。虽然类型和属性作为 Android SELinux 政策的一部分会进行定期更新,但权限和类是静态定义的,并且作为新 Linux 版本的一部分也很少进行更新。

在 Android 中类的和其访问权限可以参考源码中以下文件:

system/sepolicy/private/security_classes
system/sepolicy/private/access_vectors

政策规则采用以下格式:allow source target:class permissions;,其中:

  • source: 规则主题的类型(或属性)。谁正在请求访问权限?
  • 目标: 对象的类型(或属性)。对哪些内容提出了访问权限请求?
  • 类: 要访问的对象(例如,文件、套接字)的类型。
  • 权限: 要执行的操作(或一组操作,例如读取、写入)。

当编写的规则指定了某个属性名称时,该名称会自动扩展为列出与该属性关联的所有域或类型。一些重要属性包括:

  • domain: 与所有进程类型相关联的属性
  • file_type: 与所有文件类型相关联的属性。

2.1.1. 合理使用宏

特别是对于文件访问权限,有很多种权限需要考虑。例如,read权限不足以打开相应文件或对其调用stat。为了简化规则定义,Android 提供了一组宏来处理最常见的情况。例如,若要添加open等缺少的权限,可以将上述规则改写为:

allow appdomain app_data_file:file rw_file_perms;

如需查看实用宏的更多示例,请参阅以下源码中的预定义宏文件:

/system/sepolicy/private/mls_macros // 多级安全等级相关宏
/system/sepolicy/public/global_macros // 常用宏包括类集合,权限集合和socket权限集合(常用)
/system/sepolicy/public/ioctl_macros // ioctl相关宏
/system/sepolicy/public/neverallow_macros // Google neverallow相关宏
/system/sepolicy/public/te_macros // te文件中可以使用到的宏(常用)

请尽可能使用宏,以降低因相关权限被拒而导致失败的可能性。

2.2. 安全上下文和类别

调试 SELinux 政策或为文件添加标签时(通过 file_contexts 或运行 ls -Z),可能会遇到安全上下文(也称为标签)。例如 u:r:untrusted_app:s0:c15,c256,c513,c768。安全上下文的格式为:user:role:type:sensitivity[:categories]。通常可以忽略上下文的 userrolesensitivity 字段(请参阅明确性)。上一部分介绍了 type 字段。categories 是 SELinux 中多级安全 (MLS) 支持的一部分。从 Android S 开始,类别被用于:

  • 分隔应用数据,使其不被其他应用访问。
  • 分隔不同实际用户的应用数据。

2.3. 明确性

Android 并不会使用 SELinux 提供的所有功能。阅读外部文档时,请记住以下几点:

  • AOSP 中的大部分政策都是使用内核政策语言定义的。在使用通用中间语言 (CIL) 时,会存在一些例外情况。
  • 不使用 SELinux 用户。唯一定义的用户是 u。必要时,系统会使用安全上下文的类别字段表示实际用户。
  • 不使用 SELinux 角色和基于角色的访问权限控制 (RBAC)。定义并使用了两个默认角色:r(适用于进程)和 object_r(适用于对象)。
  • 不使用 SELinux 敏感度。已始终设置好默认的 s0 敏感度。
  • 不使用 SELinux 布尔值。一旦设备政策构建完成,该政策不再取决于设备状态。这简化了政策的审核和调试过程。

3. 实现SELinux

3.1. 关键文件

Android SELinux 原生的相关权限文件在/system/sepolicy/目录中,这里包含了绝大部分 Android 系统所需权限,同时部分权限向 vendor 公开:

  • system/sepolicy/public。其中包括所导出的用于供应商特定政策的政策。将此目录视为相应平台的已导出政策 API:处理 /system 与 /vendor 之间的接口的所有内容都位于这里。
  • system/sepolicy/private。包括系统映像正常运行所必需(但供应商映像政策应该不知道)的政策。
  • system/sepolicy/vendor。包括位于 /vendor 但存在于核心平台树(非设备特定目录)中的组件的相关政策。这是构建系统区分设备和全局组件的软件工件;从概念上讲,这是下述设备专用政策的一部分。

通常情况下,不能直接修改 system/sepolicy 文件,但可以添加或修改自己的设备专用政策文件(位于 /device/manufacturer/device-name/sepolicy 目录中)。在 Android 8.0 及更高版本中,对这些文件所做的更改只会影响供应商目录中的政策。

3.1.1. 政策文件

*.te 结尾的文件是 SELinux 政策源代码文件,用于定义域及其标签。

3.1.2. 上下文的描述文件

可以在上下文的描述文件中为对象指定标签。

  • file_contexts 用于为文件分配标签,并且可供多种用户空间组件使用。普通读写文件上下文描述可以通过 ls -Z 指令查询。
  • genfs_contexts 用于为不支持扩展属性的文件系统(proc/vfat/sys等)分配标签。此配置会作为内核政策的一部分进行加载,但更改可能对内核 inode 无效。如果在file_contexts配置没有生效时就考虑在这里文件中配置文件上下文。
  • property_contexts 用于为 Android 系统属性分配标签,以便控制哪些进程可以设置这些属性。在启动期间,init 进程会读取此配置。属性上下文描述可以通过 getprop -Z 指令查询,或者在 dev/__properties__/ 目录下执行 ls -Z 指令查询。
  • service_contexts 用于为 Android Binder 服务分配标签,以便控制哪些进程可以为相应服务添加(注册)和查找(查询)Binder 引用。在启动期间,servicemanager 进程会读取此配置。
  • seapp_contexts 用于为应用进程和 /data/data 目录分配标签。在每次应用启动时,zygote 进程都会读取此配置;在启动期间,installd 会读取此配置。
  • mac_permissions.xml 用于根据应用签名和应用软件包名称(后者可选)为应用分配 seinfo 标记。随后,分配的 seinfo 标记可在 seapp_contexts 文件中用作密钥,以便为带有该 seinfo 标记的所有应用分配特定标签。在启动期间,system_server 会读取此配置。

为便于区别平台和供应商 sepolicy,系统以不同方式构建 SELinux 上下文文件以使它们分离开来。除了 service_contexts ,其他的上下文描述文件在 systemvendor 中都各有一份并同时被加载。而 service_contexts 被拆分了成了以下文件:

  • service_contexts servicemanager 专用 service_context。平台和设备各有一份。
  • hwservice_contexts hwservicemanager 的 hwservice_context。平台和设备各有一份。
  • vndservice_contexts vndservicemanager 的 vndservice_context,需要注意的时,这个文件在平台端没有。

3.1.3. BoardConfig.mk makefile

修改或添加政策文件和上下文的描述文件后,需要更新的 /device/manufacturer/device-name/BoardConfig.mk makefile 以引用 sepolicy 子目录和每个新的政策文件。 设备独有的政策应该被放置在 device/<vendor>/<board>/sepolicy 子目录并由 BOARD_VENDOR_SEPOLICY_DIRS 变量指向其路径。 例如:

BOARD_VENDOR_SEPOLICY_DIRS += device/samsung/tuna/sepolicy // 包含设备专用政策,以及对政策进行的设备自定义(在 Android 8.0 及更高版本中,该政策对应于供应商映像组件的相关政策)。

除了 vendor 政策目录,OEMs 也能够添加 system_ext 和 product 分区的 public 和 private 政策。 例如:

SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS += device/acme/roadrunner-sepolicy/systemext/public // 包括所导出的用于供应商特定政策的政策。已安装到 system_ext 分区。
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += device/acme/roadrunner-sepolicy/systemext/private // 包括 system_ext 映像正常运行所必需(但供应商映像政策应该不知道)的政策。已安装到 system_ext 分区。
PRODUCT_PUBLIC_SEPOLICY_DIRS += device/acme/roadrunner-sepolicy/product/public // 包括所导出的用于供应商特定政策的政策。已安装到 product 分区。
PRODUCT_PRIVATE_SEPOLICY_DIRS += device/acme/roadrunner-sepolicy/product/private // 包括 product 映像正常运行所必需(但供应商映像政策应该不知道)的政策。已安装到 product 分区。

3.2. 实现

如需开始使用 SELinux,请执行以下操作:

  1. 在内核中启用 SELinux:CONFIG_SECURITY_SELINUX=y
  2. 在设备的 BoardConfig.mk 更改 kernel_cmdline 参数: BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive 这仅适用于初始制定设备政策的情况。在拥有初始引导开机程序政策后,请移除此参数,以便将设备恢复强制模式,否则设备将无法通过 CTS 验证。如果需要在设备启动之后再设置宽容模式可以使用 setenforce 0 命令来主动开启宽容模式。
  3. 以宽容模式启动系统,看看在启动时会遇到哪些拒绝事件: adb shell su -c dmesg | grep denied 或者 adb shell su -c logcat | grep denied
  4. 评估与以下内容类似的警告的输出:init: Warning! Service name needs a SELinux domain defined; please fix!。此类报错说明没有为从 init 衍生的服务添加安全域,此时就算是处于宽容模式进程仍然无法启动。
  5. 标识设备(dev目录下的设备文件,一般标识在 device.te 文件中)以及需要添加标签的其他新文件(其他文件,一般添加标签都是添加到上文描述文件对应的 .te 文件中,例如属性标签上下文描述文件为 property_contexts ,则标签定义在 property.te 文件中)。
  6. 为对象使用现有标签或新标签。查看 *_contexts 文件,了解之前是如何为内容添加标签的,然后根据对标签含义的了解分配一个新标签。这个标签最好是能够融入到政策中的现有标签,但有时也需要使用新标签,而且还需要提供关于访问该标签的规则(在 te 文件中制定)。将标签添加到相应的上下文的描述文件中。
  7. 标识应该拥有自己的安全域的域/进程。可能需要为每一项分别编写一个全新的政策。例如,从 init 衍生的所有服务都应该有自己的安全域。以下命令可以查看保持运行的服务:ps -Z,而查询所有服务上下文可以通过 ps -AZ 完整查询。
  8. 查看编译生成的所有 vendorrc 文件(在 out/target/product/device/vendor/etc/init 目录)以发现没有域类型的域。请在开发过程早期为其提供相应的域,以避免向 init 添加规则或将 init 访问权限与其自身政策中的访问权限混淆。
  9. 设置 BOARD_CONFIG.mk 中前面介绍的 vendor 以及 OEMs 相关政策变量路径。
  10. 确保每一次使用 mount 都对应一个添加了适当标签的文件系统,或者指定了 context= mount 选项。
  11. 查看每个拒绝事件,并创建 SELinux 政策来妥善处理每个拒绝事件。

3.2.1. neverallow 规则

SELinux neverallow 规则用于禁止在任何情况下都不应该发生的行为。 通过执行兼容性测试,现在各种设备上都会强制执行 SELinux neverallow 规则。

以下准则旨在协助制造商在自定义过程中避免出现与 neverallow 规则相关的错误。

4. 政策兼容性

4.1. 对象所有权和标签

在 Android 8.0 及更高版本中自定义政策时,必须为每个对象明确定义所有权,以使平台政策与供应商政策保持分离。例如,如果供应商先标记了 /dev/foo,而后平台在后续 OTA 中也标记了 /dev/foo,就会出现未定义的行为。对于 SELinux,这表现为标签冲突。设备节点只能有一个标签,解析为最后应用的标签。因此:

  • 如果进程需要访问未成功应用的标签,则会失去相应资源的访问权限。
  • 由于创建了错误的设备节点,因此已获得文件访问权限的进程可能会中断。

系统属性也有可能存在命名冲突,这样可能会导致系统上(以及 SELinux 标签)出现未定义的行为。具有 SELinux 标签的任何对象(包括属性、服务、进程、文件和套接字)都可能会出现平台标签与供应商标签冲突的情况。为了避免此类问题,请明确定义这些对象的所有权。

除了标签冲突之外,SELinux 类型/属性名称也可能会出现冲突。类型/属性名称冲突总是会导致政策编译器错误。

4.2. 系统属性和进程标签所有权

为了避免标签冲突,最有效的解决方法是使用属性命名空间。如需轻松识别平台属性并在重命名或添加导出的平台属性时避免名称冲突,请确保所有供应商属性都有各自的前缀:

属性类型 可接受的前缀
可读写 vendor.
只读 ro.vendor. ro.boot. ro.hardware.
持久性 persist.vendor.

对于非系统分区的 init rc 文件中的服务,init rc 文件中的所有供应商服务都应带有 vendor.。对供应商属性的 SELinux 标签应用类似的规则(供应商属性应带有 vendor_)。

4.3. 文件所有权

  • /system

    只有系统映像能够通过 file_contextsservice_contexts 等为 /system 组件提供标签。如果在 /vendor 政策中添加了 /system 组件的标签,则仅针对框架的 OTA 更新可能无法实现。

  • /vendor

    AOSP SELinux 政策已经标记了平台与之交互的 vendor 分区部分,这样便可以为平台进程编写 SELinux 规则,使其能够访问 vendor 分区的某些部分并/或与之通信。

    因此,在 vendor 分区中标记额外的文件时,必须遵循特定规则(通过 neverallows 强制执行):

    1. vendor_file 必须是 vendor 分区中所有文件的默认标签。平台政策要求使用此标签来访问直通式 HAL 实现。

    2. 通过供应商 SEPolicy 在 vendor 分区中添加的所有新可执行类型(exec_type)均必须具有 vendor_file_type 属性。这一规则通过 neverallows 强制执行。

    3. 为了避免与将来的平台/框架更新发生冲突,请避免在 vendor 分区中标记除可执行类型之外的文件。

    4. AOSP 标识的 Same-Process HAL 的所有库依赖项均必须标记为 same_process_hal_file.

  • Procfs (/proc)

    /proc 中的文件只能使用 genfscon 标签进行标记。

    建议:只有平台政策能标记 /proc。如果 vendor 进程需要访问 /proc 中当前使用默认标签 (proc) 标记的文件,则供应商政策不应明确标记它们(标记新标签),而应使用常规 proc 类型为供应商域添加规则。这样,平台更新就可以适应未来通过 procfs 公开的未来内核接口,并根据需要进行明确标记。

  • Debugfs (/sys/kernel/debug)

    Debugfs 可以在 file_contextsgenfscon 中进行标记。

  • Tracefs (/sys/kernel/debug/tracing)

    Tracefs 可以在 file_contextsgenfscon 中进行标记。

    建议:只有平台可以标记 tracefs

  • Sysfs (/sys)

    /sys 中的文件可以使用 file_contextsgenfscon 进行标记。平台和供应商都可以使用 file_contextsgenfscon 标记 sysfs 中的文件。

    建议:平台可以标记不是设备专用的 sysfs 节点。否则,只有供应商可以标记文件。

  • tmpfs

    tmpfs 标记的文件可以在 file_contexts 中进行标记。平台和供应商都会标记此处的文件。

    建议:供应商只能标记 tmpfs 标记路径下的 vendor 目录。

  • Rootfs (/)

    / 中的文件可以在 file_contexts 中进行标记。平台和供应商都可以标记此处的文件。

    建议:只有系统可以标记 / 中的文件。

  • /data

    数据通过 file_contextsseapp_contexts 的组合进行标记。

    建议:不允许供应商在 /data/vendor 之外进行标记。只有平台可以标记 /data 的其他部分。

5. 编写 SELinux 政策

在编写设备专用政策时,请按照下列步骤操作。

5.1. 在宽容模式下运行设备或程序

当设备处于宽容模式时(如何开启宽容模式见前文),拒绝事件会被记录下来,但不会被强制执行。宽容模式非常重要,原因有以下两点:

  • 宽容模式可确保政策启用不会延误其他早期设备启动任务。
  • 被强制执行的拒绝事件可能会掩盖其他拒绝事件。例如,文件访问通常会涉及目录搜索、文件打开和文件读取操作。在强制模式下,只会发生目录搜索拒绝事件。宽容模式可确保所有拒绝事件都会显示出来。

可以通过以下命令确认宽容模式:

adb shell getenforce

5.2. 解决核心服务生成的拒绝事件

核心服务生成的拒绝事件通常是通过为文件 添加标签 来解决的,同时核心服务一般默认权限都是正常的,不需要额外添加。例如:

avc: denied { open } for path="/dev/block/mmcblk0p2" dev="tmpfs" ino=368 scontext=u:r:hal_bootctl_default:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=1

是完全通过为 /dev/block/mmcblk0p2 添加适当的标签来解决的。在此示例中,tcontextblock_device。这表示默认环境,在该环境中,/dev/block 中的内容都会获得 block_device 标签(被分配了更具体的标签的内容除外)。

这里看到 mmcblk0p2 这个块设备名字并不具有一致性,那么为什么核心服务会访问到呢?查看代码发现其实核心服务访问的是 /dev/block/by-name/misc ,其实也就是想访问 misc 分区,而 misc 分区对应的块设备正是这个。

lrwxrwxrwx 1 root root   20 1970-01-01 00:00 misc -> /dev/block/mmcblk0p2

要解决这种问题,可以为文件添加更具体的标签,在此示例中需要修改块设备文件上下文描述为 misc_block_device。由于 hal_bootctl_default 在核心政策中已有访问 misc_block_device 所需的必要权限,因此不再需要更多权限。 其他需要以核心政策中预定义的类型作为标签的设备专用文件:

  • 块存储设备 (*_block_device)
  • 音频设备 (audio_device)
  • 视频设备 (video_device)
  • 传感器 (sensors_device)
  • NFC (nfc_device)
  • gps_device
  • /sys 中的文件
  • /proc 中的文件

一般情况下,向默认标签授予权限的做法是错误的。其中许多权限都是 neverallow 规则所不允许的,但即使该规则并未明确禁止这些权限,也最好是提供具体标签。

5.3. 为新服务添加标签并解决拒绝事件

通过 init 启动的服务需要在各自的 SELinux 域中运行。以下示例会将服务“hal_systemcontrol_default”放入它自己的 SELinux 网域中并为其授予权限。 该服务是在rc文件中启动的,如下所示:

service vendor.sstar.hardware.systemcontrol /vendor/bin/hw/vendor.sstar.hardware.systemcontrol-service
    class hal
    user system
    group system
  1. 创建一个新网域“hal_systemcontrol_default”

    创建包含以下内容的文件 device/manufacturer/device-name/sepolicy/hal_systemcontrol_default.te:

    type hal_systemcontrol_default, domain
    type hal_systemcontrol_default_exec, exec_type, file_type, vendor_file_type;
    
    init_daemon_domain(hal_systemcontrol_default)
    

    这是 hal_systemcontrol_default SELinux 网域的初始模板,可以根据该可执行文件执行的具体操作为该模板添加规则。

  2. /vendor/bin/hw/vendor.sstar.hardware.systemcontrol-service 添加标签 将以下内容添加到 device/manufacturer/device-name/sepolicy/file_contexts

    /vendor/bin/hw/vendor.sstar.hardware.systemcontrol-service    u:object_r:hal_systemcontrol_default_exec:s0
    

    这可确保为该可执行文件添加适当的标签,以便 SELinux 在适当的网域中运行相应服务。在这里 hal_systemcontrol_default_exec 类型是由 init_daemon_domain(hal_systemcontrol_default) 中定义的。

  3. 编译并刷写启动映像和系统映像。

  4. 优化相应域的 SELinux 规则。

6. 一些例子

6.1. HWComposer HAL 权限设定

抓取 HWComposer HAL 相关的 SELinux 拒绝log如下:

Line 2299: 01-01 00:00:16.292   249   249 I android.hardwar: type=1400 audit(0.0:34): avc: denied { read } for name="vndbinder" dev="binder" ino=6 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2302: 01-01 00:00:16.292   249   249 I android.hardwar: type=1400 audit(0.0:35): avc: denied { write } for name="vndbinder" dev="binder" ino=6 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2307: 01-01 00:00:16.292   249   249 I android.hardwar: type=1400 audit(0.0:36): avc: denied { open } for path="/dev/binderfs/vndbinder" dev="binder" ino=6 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2312: 01-01 00:00:16.296   249   249 I android.hardwar: type=1400 audit(0.0:37): avc: denied { ioctl } for path="/dev/binderfs/vndbinder" dev="binder" ino=6 ioctlcmd=0x6209 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2316: 01-01 00:00:16.296   249   249 I android.hardwar: type=1400 audit(0.0:38): avc: denied { map } for path="/dev/binderfs/vndbinder" dev="binder" ino=6 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2361: 01-01 00:00:16.552   249   249 I android.hardwar: type=1400 audit(0.0:47): avc: denied { create } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2361: 01-01 00:00:16.552   249   249 I android.hardwar: type=1400 audit(0.0:47): avc: denied { create } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2363: 01-01 00:00:16.556   249   249 I android.hardwar: type=1400 audit(0.0:48): avc: denied { bind } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2363: 01-01 00:00:16.556   249   249 I android.hardwar: type=1400 audit(0.0:48): avc: denied { bind } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2377: 01-01 00:00:16.556   249   249 I uevent-listener: type=1400 audit(0.0:49): avc: denied { read } for path="socket:[15344]" dev="sockfs" ino=15344 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2377: 01-01 00:00:16.556   249   249 I uevent-listener: type=1400 audit(0.0:49): avc: denied { read } for path="socket:[15344]" dev="sockfs" ino=15344 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2502: 01-01 00:00:17.576   249   249 I HwBinder:249_1: type=1400 audit(0.0:55): avc: denied { getattr } for path="/dev/dri/card0" dev="tmpfs" ino=493 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
Line 2503: 01-01 00:00:17.576   249   249 I HwBinder:249_1: type=1400 audit(0.0:56): avc: denied { read write } for name="card0" dev="tmpfs" ino=493 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
Line 2504: 01-01 00:00:17.628   154   154 E SELinux : avc:  denied  { add } for pid=249 uid=1000 name=vendor.sstar.hardware.transmission.IComposerTransmission/default scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=1
Line 2520: 01-01 00:00:17.576   249   249 I HwBinder:249_1: type=1400 audit(0.0:57): avc: denied { open } for path="/dev/dri/card0" dev="tmpfs" ino=493 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
Line 2529: 01-01 00:00:17.576   249   249 I HwBinder:249_1: type=1400 audit(0.0:58): avc: denied { ioctl } for path="/dev/dri/card0" dev="tmpfs" ino=493 ioctlcmd=0x64a0 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
Line 2531: 01-01 00:00:17.628   249   249 I HwBinder:249_1: type=1400 audit(0.0:59): avc: denied { call } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=1
Line 2538: 01-01 00:00:17.628   249   249 I HwBinder:249_1: type=1400 audit(0.0:60): avc: denied { transfer } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=1
Line 2539: 01-01 00:00:17.680   252   252 I android.hardwar: type=1400 audit(0.0:61): avc: denied { call } for scontext=u:r:hal_tv_input_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=binder permissive=1
Line 2545: 01-01 00:00:17.680   252   252 I android.hardwar: type=1400 audit(0.0:62): avc: denied { transfer } for scontext=u:r:hal_tv_input_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=binder permissive=1
Line 2546: 01-01 00:00:17.680   249   249 I Binder:249_3: type=1400 audit(0.0:63): avc: denied { call } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_tv_input_default:s0 tclass=binder permissive=1
Line 2547: 01-01 00:00:17.680   249   249 I Binder:249_3: type=1400 audit(0.0:64): avc: denied { use } for path="/dev/dri/card0" dev="tmpfs" ino=493 scontext=u:r:hal_tv_input_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=fd permissive=1

因为 HWComposer HAL 服务使用的是 AOSP 原生服务安全域,因此不需要为服务添加新的安全域,HWComposer HAL 服务的安全域为 hal_graphics_composer_default。 一般而言,AOSP HAL 服务在 system/sepolicy/vendor/ 目录下都有对应的政策文件(.te)文件,HWComposer HAL 对应的政策文件为:hal_graphics_composer_default.te。最好在供应商的政策目录下需要创建相同名字的 .te 政策文件并添加额外的政策。

分解前面抓到的 log 分解成以下几个部分为其加权限。

6.1.1. 添加对于 vndbinder 的访问权限

Line 2299: 01-01 00:00:16.292   249   249 I android.hardwar: type=1400 audit(0.0:34): avc: denied { read } for name="vndbinder" dev="binder" ino=6 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2302: 01-01 00:00:16.292   249   249 I android.hardwar: type=1400 audit(0.0:35): avc: denied { write } for name="vndbinder" dev="binder" ino=6 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2307: 01-01 00:00:16.292   249   249 I android.hardwar: type=1400 audit(0.0:36): avc: denied { open } for path="/dev/binderfs/vndbinder" dev="binder" ino=6 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2312: 01-01 00:00:16.296   249   249 I android.hardwar: type=1400 audit(0.0:37): avc: denied { ioctl } for path="/dev/binderfs/vndbinder" dev="binder" ino=6 ioctlcmd=0x6209 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1
Line 2316: 01-01 00:00:16.296   249   249 I android.hardwar: type=1400 audit(0.0:38): avc: denied { map } for path="/dev/binderfs/vndbinder" dev="binder" ino=6 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=1

这部分 log 说明 HWComposer HAL 缺少对于 vndbinder 的访问权限,可以直接在 hal_graphics_composer_default.te 文件中添加如下:

vndbinder_use(hal_graphics_composer_default)

这里使用了 vndbinder_use 快速的完成 hal_graphics_composer_default 对于 vndbinder 的访问权限。

Line 2361: 01-01 00:00:16.552   249   249 I android.hardwar: type=1400 audit(0.0:47): avc: denied { create } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2361: 01-01 00:00:16.552   249   249 I android.hardwar: type=1400 audit(0.0:47): avc: denied { create } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2363: 01-01 00:00:16.556   249   249 I android.hardwar: type=1400 audit(0.0:48): avc: denied { bind } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2363: 01-01 00:00:16.556   249   249 I android.hardwar: type=1400 audit(0.0:48): avc: denied { bind } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2377: 01-01 00:00:16.556   249   249 I uevent-listener: type=1400 audit(0.0:49): avc: denied { read } for path="socket:[15344]" dev="sockfs" ino=15344 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1
Line 2377: 01-01 00:00:16.556   249   249 I uevent-listener: type=1400 audit(0.0:49): avc: denied { read } for path="socket:[15344]" dev="sockfs" ino=15344 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=netlink_kobject_uevent_socket permissive=1

对于 netlink_kobject_uevent_socket 权限设定比较简单,直接添加即可。

allow hal_graphics_composer_default self:netlink_kobject_uevent_socket creat_socket_perms_no_ioctl;

这里 creat_socket_perms_no_ioctl 同时是使用的宏来快速完成权限设定。

6.1.3. 添加对于 /dev/dri/card0 节点的访问权限

Line 2502: 01-01 00:00:17.576   249   249 I HwBinder:249_1: type=1400 audit(0.0:55): avc: denied { getattr } for path="/dev/dri/card0" dev="tmpfs" ino=493 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
Line 2503: 01-01 00:00:17.576   249   249 I HwBinder:249_1: type=1400 audit(0.0:56): avc: denied { read write } for name="card0" dev="tmpfs" ino=493 scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

/dev/dri/card0 作为标准的 DRM 设备节点,一般而言不会使用供应商添加的新标签来标记其上下文,在这里使用公共政策中的 gpu_device 标签标记它。在 vendor 的 file_contexts 文件中添加其上下文如下:

/dev/dri(/*.)?   u:object_r:gpu_device:s0

因为 hal_graphics_composer_default 在公共政策中就有对于 gpu_device 的访问权限,因此不需要再额外添加其他。

6.1.4. 添加对于 vendor.sstar.hardware.transmission.IComposerTransmission/default binder 服务的访问权限

Line 2504: 01-01 00:00:17.628   154   154 E SELinux : avc:  denied  { add } for pid=249 uid=1000 name=vendor.sstar.hardware.transmission.IComposerTransmission/default scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=1

由于 vendor.sstar.hardware.transmission.IComposerTransmission/default 没有设定上下文,因此使用的是 default_android_service 这个默认标签,这里不能使用这个标签为其添加权限。因此首先需要为该 binder 服务添加一个标签。需要在 vendor 的 vndservice.te 添加类型:

type composertransmission_service, vendor_service, vndservice_manager_type;

vndservice_contexts 中添加上下文描述。

vendor.sstar.hardware.transmission.IComposerTransmission/default    u:object_r:composertransmission_service:s0

这样就能够在 hal_graphics_composer_default.te 文件中添加权限了:

add_service(hal_graphics_composer_default, composertransmission_service)

这里又是通过宏 add_service 完成 hal_graphics_composer_default 对于 composertransmission_service 类型的 binder 服务进行服务添加和查询的权限。

6.1.5. 添加和 hal_tv_input_default binder 通讯访问权限

Line 2531: 01-01 00:00:17.628   249   249 I HwBinder:249_1: type=1400 audit(0.0:59): avc: denied { call } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=1
Line 2538: 01-01 00:00:17.628   249   249 I HwBinder:249_1: type=1400 audit(0.0:60): avc: denied { transfer } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=1
Line 2539: 01-01 00:00:17.680   252   252 I android.hardwar: type=1400 audit(0.0:61): avc: denied { call } for scontext=u:r:hal_tv_input_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=binder permissive=1
Line 2545: 01-01 00:00:17.680   252   252 I android.hardwar: type=1400 audit(0.0:62): avc: denied { transfer } for scontext=u:r:hal_tv_input_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=binder permissive=1
Line 2546: 01-01 00:00:17.680   249   249 I Binder:249_3: type=1400 audit(0.0:63): avc: denied { call } for scontext=u:r:hal_graphics_composer_default:s0 tcontext=u:r:hal_tv_input_default:s0 tclass=binder permissive=1
Line 2547: 01-01 00:00:17.680   249   249 I Binder:249_3: type=1400 audit(0.0:64): avc: denied { use } for path="/dev/dri/card0" dev="tmpfs" ino=493 scontext=u:r:hal_tv_input_default:s0 tcontext=u:r:hal_graphics_composer_default:s0 tclass=fd permissive=1

在 HWComposer HAL 中客制化了和 TV input HAL 的 binder 通讯,这里只需要在 hal_graphics_composer_default.te 文件中添加如下 binder 交互权限:

binder_call(hal_graphics_composer_default, hal_tv_input_default)
binder_call(hal_tv_input_default, hal_graphics_composer_default)

binder_call 宏可以快捷的完成 binder 通讯相关的权限设定。

至此, HWComposer HAL 相关的 SELinux 权限设定就已经完成了。

6.2. SystemControl HAL 权限设定

抓取 SystemControl HAL 相关的 SELinux 拒绝 log 如下:

Line 1747: 01-01 00:00:13.300   260   260 I vendor.sstar.ha: type=1400 audit(0.0:36): avc: denied { write } for name="system_control" dev="mmcblk0p16" ino=8218 scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=dir permissive=1
Line 1748: 01-01 00:00:13.300   260   260 I vendor.sstar.ha: type=1400 audit(0.0:37): avc: denied { add_name } for name="system_control_user_configuration.xml" scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=dir permissive=1
Line 1749: 01-01 00:00:13.300   260   260 I vendor.sstar.ha: type=1400 audit(0.0:38): avc: denied { create } for name="system_control_user_configuration.xml" scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=file permissive=1
Line 1750: 01-01 00:00:13.300   260   260 I vendor.sstar.ha: type=1400 audit(0.0:39): avc: denied { write open } for path="/data/vendor/hardware/system_control/system_control_user_configuration.xml" dev="mmcblk0p16" ino=8220 scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=file permissive=1
Line 1753: 01-01 00:00:13.423   153   153 E SELinux : avc:  denied  { add } for pid=260 uid=1000 name=vendor.sstar.hardware.systemcontrol.ISystemControl/default scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=1
Line 1760: 01-01 00:00:13.416   260   260 I vendor.sstar.ha: type=1400 audit(0.0:40): avc: denied { read } for name="system_control_user_configuration.xml" dev="mmcblk0p16" ino=8220 scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=file permissive=1
Line 1761: 01-01 00:00:13.416   260   260 I vendor.sstar.ha: type=1400 audit(0.0:41): avc: denied { getattr } for path="/data/vendor/hardware/system_control/system_control_user_configuration.xml" dev="mmcblk0p16" ino=8220 scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=file permissive=1
Line 1764: 01-01 00:00:13.420   260   260 I vendor.sstar.ha: type=1400 audit(0.0:42): avc: denied { call } for scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=1
Line 1766: 01-01 00:00:13.420   260   260 I vendor.sstar.ha: type=1400 audit(0.0:43): avc: denied { transfer } for scontext=u:r:vendor_hal_systemcontrol_sstar:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=1

SystemControl HAL 是供应商新增的 HAL 服务,在前文中已经讲诉如何为其添加安全域,下面讲说明如何为该域添加完成的访问权限。

6.2.1. 对于 config xml 文件的权限设定

Line 1748: 01-01 00:00:13.300   260   260 I vendor.sstar.ha: type=1400 audit(0.0:37): avc: denied { add_name } for name="system_control_user_configuration.xml" scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=dir permissive=1
Line 1749: 01-01 00:00:13.300   260   260 I vendor.sstar.ha: type=1400 audit(0.0:38): avc: denied { create } for name="system_control_user_configuration.xml" scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=file permissive=1
Line 1750: 01-01 00:00:13.300   260   260 I vendor.sstar.ha: type=1400 audit(0.0:39): avc: denied { write open } for path="/data/vendor/hardware/system_control/system_control_user_configuration.xml" dev="mmcblk0p16" ino=8220 scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=file permissive=1
Line 1760: 01-01 00:00:13.416   260   260 I vendor.sstar.ha: type=1400 audit(0.0:40): avc: denied { read } for name="system_control_user_configuration.xml" dev="mmcblk0p16" ino=8220 scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=file permissive=1
Line 1761: 01-01 00:00:13.416   260   260 I vendor.sstar.ha: type=1400 audit(0.0:41): avc: denied { getattr } for path="/data/vendor/hardware/system_control/system_control_user_configuration.xml" dev="mmcblk0p16" ino=8220 scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:object_r:vendor_data_file:s0 tclass=file permissive=1

system_control_user_configuration.xml 是由 SystemControl HAL 从 vendor/etc/system_control/ 目录拷贝到 /data/vendor/hardware/system_control/ 目录的文件,由于 system_control_user_configuration.xml 没有设定标签,因此使用了默认标签 vendor_data_file ,这里也是不能直接对于默认标签赋予权限的。因此需要修改 system_control_user_configuration.xml 的标签,由于文件是由该进程创建的,因此可以使用以下方式快速进行权限赋予。在 hal_systemcontrol_default.te 中添加如下:

type systemcontrol_configs_file, file_type
file_type_auto_trans(hal_systemcontrol_default, vendor_data_file, systemcontrol_configs_file)

上面的权限赋予中先定义了一个文件类型 systemcontrol_configs_file ,然后通过宏 file_type_auto_trans 快速完成文件类型转换。具体实现逻辑可以参考宏的定义内容,这里不再赘述。 如果没有使用以上的宏来完成文件类型自动转换,那么常规的政策设定会如下: 首先在 file.te 添加标签定义:

type systemcontrol_configs_file, file_type

之后在 file_contexts 中添加上下文:

/data/vendor/hardware/system_control/system_control_user_configuration.xml    u:object_r:systemcontrol_configs_file:s0

最后在 hal_systemcontrol_default.te 中添加政策如下:

allow hal_systemcontrol_default systemcontrol_configs_file:file rw_file_perms

显然这种配置方式较宏来完成配置会显得比较冗余。

6.2.2. 对于 aidl 接口服务器端的权限设定

Line 1753: 01-01 00:00:13.423   153   153 E SELinux : avc:  denied  { add } for pid=260 uid=1000 name=vendor.sstar.hardware.systemcontrol.ISystemControl/default scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=1
...
Line 1764: 01-01 00:00:13.420   260   260 I vendor.sstar.ha: type=1400 audit(0.0:42): avc: denied { call } for scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=1
Line 1766: 01-01 00:00:13.420   260   260 I vendor.sstar.ha: type=1400 audit(0.0:43): avc: denied { transfer } for scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=1

SystemControl HAL 作为一个 aidl 接口的服务器端需要完成接口 binder 服务添加以及一些 binder 通讯设定,这里和前面讲述的不太相同,因为这里 SystemControl 是作为一个 HAL 服务进程,而前文只是单纯的使用 aidl 接口进行 HAL 之间的 binder 通讯。作为 HAL ,那么 binder 通讯必须在 dev/binder 下,而不是 dev/vndbinder 下。所以首先还是需要为 vendor.sstar.hardware.systemcontrol.ISystemControl/default binder 服务添加标签。这里需要添加到 service_contexts 而不是 vndservice_contexts

首先在 service.te 添加 binder 服务类型:

type hal_systemcontrol_service, vendor_service, service_manager_type

之后在 service_contexts 添加上下文描述:

vendor.sstar.hardware.systemcontrol.ISystemControl/default    u:object_r:hal_systemcontrol_service:s0

最后在 hal_systemcontrol_default.te 添加具体政策:

hal_attribute(systemcontrol)
hal_server_domain(hal_systemcontrol_default, hal_systemcontrol)
hal_attribute_service(hal_systemcontrol, hal_systemcontrol_service)
binder_use(hal_systemcontrol_default)

这里同样通过几个 hal 相关的宏继续快速的权限配置。

至此,SystemControl HAL 的 SELinux 权限设定已经全部完成。

7. 注意事项

7.1. 文件合并导致权限异常问题

在前文已经提及可以通过特定宏去包含多个路径下的 SELinux 政策文件,多个路径下的相关配置会合并在一起。在这里有一点需要十分注意,那就是每个文件的末尾必须添加一行空白行保证如果和其他文件合并时不会出问题。例如如果同时通过 BOARD_VENDOR_SEPOLICY_DIRS 宏包含的两个不同路径下都有 service_contexts 文件分别描述如下:

vendor.sstar.hardware.systemcontrol.ISystemControl/default         u:object_r:systemcontrol_service:s0
tv_remote          u:object_r:tv_remote_service:s0

此时两个文件末尾都没有加空行,那么就会导致合并之后的文件描述变成如下:

vendor.sstar.hardware.systemcontrol.ISystemControl/default         u:object_r:systemcontrol_service:s0tv_remote          u:object_r:tv_remote_service:s0

vendor.sstar.hardware.systemcontrol.ISystemControl/default 这个binder服务的上下文被异常改变了,因此运行设备时会出现以下报错:

01-01 00:00:20.098   167   167 E SELinux : avc:  denied  { add } for pid=468 uid=1000 name=vendor.sstar.hardware.systemcontrol.ISystemControl/default scontext=u:r:hal_systemcontrol_default:s0 tcontext=u:object_r:hal_systemcontrol_service:s0tv_remote tclass=service_manager permissive=0

报错原因正是由于上下文由原来的 u:object_r:hal_systemcontrol_service:s0 被异常改变成了 u:object_r:hal_systemcontrol_service:s0tv_remote ,因此出现未赋权而被拒绝。

为了避免以上问题,所有的 SELinux 权限配置 文件末尾都应该加上空行 以避免此问题产生。

7.2. 触发 neverallow 导致的编译报错问题

在添加权限时,有时候会遇到添加的规则触发 neverallow 导致的编译问题,这种问题原因可能多种多样,通常我们可以通过编译报错的 log 找到触发 neverallow 的条目,再使用合理的方式解决它。

假设我们需要在 codec2 HAL 中需要添加对于 “debug.vendor.codec2.enable” 属性值的设定,通过 avc 的 log 知道 “debug.vendor.codec2.enable” 的默认上下文标签为 debug_prop,因此在对应的 mediacodec.te 文件中添加如下权限:

// mediacodec.te
set_prop(mediacodec, debug_prop)

执行重新编译代码之后,报出如下错误信息:

neverallow check failed at out/target/product/pioneer5_sdp/obj/ETC/plat_sepolicy.cil_intermediates/plat_sepolicy.cil:22957 from system/sepolicy/private/property.te:151
  (neverallow base_typeattr_755 base_typeattr_756 (property_service (set)))
    <root>
    allow at out/target/product/pioneer5_sdp/obj/ETC/vendor_sepolicy.cil_intermediates/vendor_sepolicy.cil:1336
      (allow mediacodec debug_prop_32_0 (property_service (set)))

根据前文所述,这里根据 log 找到触发 neverallow 的条目为 system/sepolicy/private/property.te 文件的 151 行。通过源码找到该政策文件的 151 行描述如下:

// system/sepolicy/private/property.te
 compatible_property_only(`
 # Prevent properties from being set
   neverallow {
     domain
     -coredomain
     -appdomain
     -vendor_init
   } {
     core_property_type
     extended_core_property_type
     exported_config_prop
     exported_default_prop
     exported_dumpstate_prop
     exported_system_prop
     exported3_system_prop
     usb_control_prop
     -nfc_prop
     -powerctl_prop
     -radio_prop
   }:property_service set;

这条 neverallow 的含义大致为不允许除了 coredomain,appdomain 和 vendor_init 之外的 domain 对 core_property_type 等进行 property_service 的 set 操作。由于 mediacodec 不属于 coredomain,appdomain 和 vendor_init,因此它适配该 neverallow 条目,而 debug_prop 又存在如下定义:

// system/sepolicy/public/property.te
typeattribute debug_prop         core_property_type;

由上可知 debug_prop 属于 core_property_type 类型,由此它也满足以上的 neverallow 条目。

综上所述,mediacodec 无法直接对于 debug_prop 类型的属性进行设定。这个时候要解决此问题方案有两个:

  1. 修改 mediacodec 让其属于 coredomain 或者 appdomain;
  2. 给 “debug.vendor.codec2.enable” 添加新的上下文,使其不再是默认的 debug_prop 上下文。

对于第一个方案显然是行不通的,因为 mediacodec 定义是原生的定义,一般不能去修改。所以此问题就需要修改 “debug.vendor.codec2.enable” 的上下文标签。如前面章节介绍,一般对于新增的设备节点,属性等都最好添加独有的上下文标签,避免使用默认标签,因为默认标签会增大权限范围,同时容易触发 neverallow 规则。

经过前文分析重新优化设定权限如下:

// property.te
vendor_public_prop(vendor_debug_codec_prop)

// property_contexts
debug.vendor.codec2.enable        u:object_r:vendor_debug_codec_prop:s0

// mediacodec.te
set_prop(mediacodec, vendor_debug_codec_prop)

通过添加全新的标签 vendor_debug_codec_prop,政策可以成功编译通过。