SELinux笔记-3-Android官方文档
注:摘录自 Android 中的安全增强型 Linux: https://source.android.com/docs/security/features/selinux?hl=zh-cn
Android 中的安全增强型 Linux
一、概述
作为 Android 安全模型的一部分,Android 使用安全增强型 Linux (SELinux) 对所有进程强制执行强制访问控制 (MAC),其中包括以 Root/超级用户权限运行的进程(Linux 功能)。很多公司和组织都为 Android 的 SELinux 实现做出了贡献。借助 SELinux,Android 可以更好地保护和限制系统服务、控制对应用数据和系统日志的访问、降低恶意软件的影响,并保护用户免遭移动设备上的代码可能存在的缺陷的影响。
SELinux 按照默认拒绝的原则运行:任何未经明确允许的行为都会被拒绝。SELinux 可按两种全局模式运行:####
(1) 宽容模式:权限拒绝事件会被记录下来,但不会被强制执行。
(2) 强制模式:权限拒绝事件会被记录下来并强制执行。
Android 中包含 SELinux(处于强制模式)和默认适用于整个 AOSP 的相应安全政策。在强制模式下,非法操作会被阻止,并且尝试进行的所有违规行为都会被内核记录到 dmesg 和 logcat####。开发时,您应该先利用这些错误信息对软件和 SELinux 政策进行优化,再对它们进行强制执行。如需了解详情,请参阅下面实现 SELinux 章节。
此外,SELinux 还支持基于域的宽容模式####。在这种模式下,可将特定域(进程)设为宽容模式,同时使系统的其余部分处于全局强制模式。简单来说,域是安全政策中用于标识一个进程或一组进程的标签,安全政策会以相同的方式处理所有具有相同域标签的进程。借助基于域的宽容模式,可逐步将 SELinux 应用于系统中越来越多的部分,还可以为新服务制定政策(同时确保系统的其余部分处于强制模式)。
1. 背景
Android 安全模型部分基于应用沙盒的概念。每个应用都在自己的沙盒内运行。在 Android 4.3 之前的版本中,这些沙盒是通过为每个应用创建独一无二的 Linux UID(在应用安装时创建)来定义的。Android 4.3 及更高版本使用 SELinux 进一步定义 Android 应用沙盒的边界。
基于 Android 4.3(宽容模式)和 Android 4.4(部分强制模式),在 Android 5.0 及更高版本中,已全面强制执行 SELinux。通过此项变更,Android 已从对有限的一组关键域####(installd、netd、vold 和 zygote)强制执行 SELinux 转为对所有域####(超过 60 个)强制执行 SELinux。具体而言:
(1) 在 Android 5.x 及更高版本中,所有域均处于强制模式。
(2) init 以外的任何进程都不应在 init 域中运行。
(3) 出现任何常规拒绝事件(对于 block_device、socket_device、default_service),都表示设备需要一个特殊域。
Android 6.0 通过降低我们政策的宽容度强化了系统安全,从而实现更好的用户隔离和 IOCTL 过滤、降低可从设备/系统之外访问的服务面临的威胁、进一步强化 SELinux 域,以及高度限制对 /proc 的访问。
Android 7.0 更新了 SELinux 配置,以进一步锁定应用沙盒并缩小受攻击面。此版本还将单片式 mediaserver 堆栈拆分为较小的进程,以缩小其权限范围。如需了解详情,请参阅利用更多的 Linux 内核防护功能保护 Android 系统和媒体堆栈安全强化。
Android 8.0 更新了 SELinux 以便与 Treble 配合使用,后者可将较低级别的供应商代码与 Android 系统框架分离开来。此版本更新了 SELinux 政策以允许设备制造商和 SoC 供应商更新自己的政策部分、构建自己的映像(vendor.img、boot.img 等),然后更新这些映像而不受平台影响,反之亦然。
虽然可以在设备上运行更高/更新版本的平台(框架),但反之并不成立;供应商映像 (vendor.img/odm.img) 的版本不能高于平台 (system.img) 的版本。因此,较新版平台可能会带来 SELinux 兼容性问题,因为平台 SELinux 政策的版本要比该政策的供应商 SELinux 部分更新。Android 8.0 模型提供了一种保持兼容性的方法,以免进行不必要的同时 OTA 更新。
2. 其他资源
如需关于构建实用 SELinux 政策的帮助,请参阅以下资源:
注意:Android 不使用某些 SELinux 概念。如需了解详情,请参阅下文的明确性。
SELinux Notebook,SELinux 的最新参考文档。此文档进一步详细介绍了政策语言、每个关键字的含义以及安全上下文的计算方式。
[] 有关强制执行 SELinux 政策的直观操作指南
[] 针对 Linux 的安全增强功能
[] 安全增强 (SE) Android:在 Android 中引入灵活 MAC
[] 将 SELinux 作为 Linux 安全模块实现
[] 配置 SELinux 政策
注:原文有部分链接。
二、SELinux 概念
1. 强制访问控制
安全增强型 Linux (SELinux) 是适用于 Linux 操作系统的强制访问控制 (MAC) 系统。作为 MAC 系统,它与 Linux 中用户非常熟悉的自主访问控制 (DAC) 系统不同。在 DAC 系统中,存在所有权的概念,即特定资源的所有者可以控制与该资源关联的访问权限。这种系统通常比较粗放,并且容易出现无意中提权的问题。MAC 系统则会在每次收到访问请求时都先咨询核心机构,再做出决定。
SELinux 已作为 Linux 安全模块 (LSM) 框架的一部分实现,该框架可识别各种内核对象以及对这些对象执行的敏感操作。其中每项操作要执行时,系统都会调用 LSM 钩子函数,以便根据不透明安全对象中存储的关于相应操作的信息来确定是否应允许执行相应操作。SELinux 针对这些钩子以及这些安全对象的管理提供了相应的实现,该实现可结合自己的政策来决定是否允许相应访问。
通过结合使用其他 Android 安全措施,Android 的访问权限控制政策能够大大降低遭到入侵的计算机和账号可能蒙受的损失。Android 的自主访问控制和强制访问控制等工具可为您提供一种结构,确保您的软件仅以最低权限级别运行。这样可降低攻击造成的影响,并降低错误进程重写数据甚至是传输数据的可能性。
在 Android 4.3 及更高版本中,SELinux 开始为传统的自主访问控制 (DAC) 环境提供强制访问控制 (MAC) 保护功能。例如,软件通常情况下必须以 root 用户账号的身份运行,才能向原始块设备写入数据。在基于 DAC 的传统 Linux 环境中,如果根用户遭到入侵,攻击者便可以利用该用户身份向每个原始块存储设备写入数据。不过,可以使用 SELinux 为这些设备添加标签,以便被分配了 root 权限的进程可以只向相关政策中指定的设备写入数据。这样一来,该进程便无法覆盖特定原始块存储设备之外的数据和系统设置。
如需更多安全威胁示例以及使用 SELinux 解决安全威胁的方法,请参阅下文用例
2. 强制执行级别
SELinux 可以在各种模式下实现:
(1) 宽容模式 - 仅记录但不强制执行 SELinux 安全政策。
(2) 强制模式 - 强制执行并记录安全政策。如果失败,则显示为 EPERM 错误。
在选择强制执行级别时只能二择其一,您的选择将决定您的政策是采取操作,还是仅允许您收集潜在的失败事件。宽容模式在实现过程中尤其有用。
3. 类型、属性和规则
Android 依靠 SELinux 的类型强制执行 (TE) 组件来实施其政策。这表示所有对象(例如文件、进程或套接字)都具有相关联的类型。例如,默认情况下,应用的类型为 untrusted_app####。对于进程而言,其类型也称为域####。可以使用一个或多个属性为类型添加注释。属性可用于同时指代多种类型。
对象会映射到类(例如文件、目录、符号链接、套接字),并且每个类的不同访问权限类型由权限表示。 例如,file 类存在权限 open。虽然类型和属性作为 Android SELinux 政策的一部分会进行定期更新,但权限和类是静态定义的,并且作为新 Linux 版本的一部分也很少进行更新。
政策规则采用以下格式:allow source target:class permissions;,其中:
(1) source - 规则主题的类型(或属性)。谁正在请求访问权限?
(2) 目标 - 对象的类型(或属性)。对哪些内容提出了访问权限请求?
(3) 类 - 要访问的对象(例如文件、套接字)的类型。
(4) 权限 - 要执行的操作(或一组操作,例如读取、写入)。
规则的一个示例如下:
allow untrusted_app app_data_file:file { read write };
这表示应用可以读取和写入带有 app_data_file 标签的文件。还有其他应用类型。例如,isolated_app 用于清单中含有 isolatedProcess=true 的应用服务。
Android 对涵盖应用的所有类型使用名为 appdomain 的属性,而不是对这两种类型重复同一规则:
# Associate the attribute appdomain with the type untrusted_app.
typeattribute untrusted_app appdomain;# Associate the attribute appdomain with the type isolated_app.
typeattribute isolated_app appdomain;allow appdomain app_data_file:file { read write };
当编写的规则指定了某个属性名称时,该名称会自动扩展为列出与该属性关联的所有域或类型。一些重要属性包括:
(1) domain - 与所有进程类型相关联的属性
(2) file_type - 与所有文件类型相关联的属性。
4. 宏
特别是对于文件访问权限,有很多种权限需要考虑。例如,read 权限不足以打开相应文件或对其调用 stat。为了简化规则定义,Android 提供了一组宏来处理最常见的情况。例如,若要添加 open 等缺少的权限,可以将上述规则改写为:
allow appdomain app_data_file:file rw_file_perms;
如需查看实用宏的更多示例,请参阅 global_macros 和 te_macros 文件。请尽可能使用宏,以降低因相关权限被拒而导致失败的可能性。
定义类型后,需要将其与所代表的文件或进程相关联。如需详细了解如何实现这种关联,请参阅下文 "实现 SELinux" 章节。如需详细了解规则,请参阅 SELinux Notebook。
5. 安全上下文和类别
调试 SELinux 政策或为文件添加标签时(通过 file_contexts 或运行 ls -Z),您可能会遇到安全上下文(也称为标签)。例如 u:r:untrusted_app:s0:c15,c256,c513,c768。安全上下文的格式为:user:role:type:sensitivity[:categories]。####您通常可以忽略上下文的 user、role 和 sensitivity 字段(请参阅下文“明确性”)。上一部分介绍了 type 字段。categories 是 SELinux 中 "多级安全 (MLS)" 支持的一部分。在 Android 12 及更高版本中,类别用于:
(1) 分隔应用数据,使其不被其他应用访问。
(2) 分隔不同实际用户的应用数据。
6. 明确性
Android 并不会使用 SELinux 提供的所有功能。阅读外部文档时,请记住以下几点:
(1) AOSP 中的大部分政策都是使用内核政策语言定义的。在使用通用中间语言 (CIL) 时####,会存在一些例外情况。
(2) 不使用 SELinux 用户。唯一定义的用户是 u。必要时,系统会使用安全上下文的类别字段表示实际用户。
(3) 不使用 SELinux 角色和基于角色的访问控制 (RBAC)。定义并使用了两个默认角色:r(适用于主题)和 object_r(适用于对象)。
(4) 不使用 SELinux 敏感度。已始终设置好默认的 s0 敏感度。
(5) 不使用 SELinux 布尔值。为设备构建政策后,政策将不依赖于设备状态。这简化了政策的审核和调试过程。
三、实现 SELinux
SELinux 被设置为“默认拒绝”模式,这表示,对于在内核中存在钩子的每一次访问,都必须获得政策的明确许可。这意味着政策文件中包含规则、类型、类、权限等方面的大量信息。关于 SELinux 的完整注意事项不在本文档的讨论范围之内,现在您必须要了解的是在启动新的 Android 设备时如何编写政策规则。目前有大量关于 SELinux 的信息可供您参考。关于建议的资源,请参阅支持文档,即“其它资源”章节。
1. 关键文件
如需启用 SELinux,请集成最新的 Android 内核,然后整合 system/sepolicy ####目录中的文件。这些文件在编译后会包含 SELinux 内核安全政策,并涵盖上游 Android 操作系统。
通常情况下,您不能直接修改 system/sepolicy 文件####,但您可以添加或修改自己的设备专用政策文件(位于 /device/manufacturer/device-name/sepolicy 目录中)。在 Android 8.0 及更高版本中,您对这些文件所做的更改只会影响供应商目录中的政策。如需详细了解 Android 8.0 及更高版本中的公共 sepolicy 分离,请参阅下文"在 Android 8.0 及更高版本中自定义 SEPolicy"章节。无论是哪个 Android 版本,您都仍需要修改以下文件:
1.1 政策文件
以 *.te 结尾的文件是 SELinux 政策源代码文件,用于定义域及其标签。您可能需要在 /device/manufacturer/device-name/sepolicy 中创建新的政策文件,但您应尽可能尝试更新现有文件。
1.2 上下文的描述文件
您可以在上下文的描述文件中为您的对象指定标签。
(1) file_contexts 用于为文件分配标签####,并且可供多种用户空间组件使用。在创建新政策时,请创建或更新该文件,以便为文件分配新标签。如需应用新的 file_contexts,请重新构建文件系统映像,或对要重新添加标签的文件运行 restorecon####????####。在升级时,对 file_contexts 所做的更改会在升级过程中自动应用于系统和用户数据分区。此外,您还可以通过以下方式使这些更改在升级过程中自动应用于其他分区:在以允许读写的方式装载相应分区后,将 restorecon_recursive ####调用添加到 init.board.rc 文件中。
(2) genfs_contexts 用于为不支持扩展属性的文件系统(例如 proc 或 vfat)####分配标签。此配置会作为内核政策的一部分进行加载,但更改可能对内核 inode 无效。要全面应用更改,您需要重新启动设备,或卸载后重新装载文件系统。 此外,通过使用 context=mount 选项,您还可以为装载的特定系统文件(例如 vfat)分配特定标签。
(3) property_contexts 用于为 Android 系统属性分配标签####,以便控制哪些进程可以设置这些属性。在启动期间,init 进程会读取此配置。
(4) service_contexts 用于为 Android binder 服务分配标签,以便控制哪些进程可以为相应服务添加(注册)和查找(查询)binder 引用。在启动期间,servicemanager 进程会读取此配置。
(5) seapp_contexts 用于为应用进程和 /data/data 目录分配标签。在每次应用启动时,zygote 进程都会读取此配置;在启动期间,installd 会读取此配置。
(6) mac_permissions.xml 用于根据应用签名和应用软件包名称(后者可选)为应用分配 seinfo 标记。随后,分配的 seinfo 标记可在 seapp_contexts 文件中用作密钥,以便为带有该 seinfo 标记的所有应用分配特定标签。在启动期间,system_server 会读取此配置。
keystore2_key_contexts 用于为密钥库 2.0 命名空间分配标签。 这些命名空间由 keystore2 守护程序强制执行。密钥库始终都提供基于 UID/AID 的命名空间。密钥库 2.0 还会强制执行 sepolicy 定义的命名空间。如需详细了解此文件的格式和规范,请点击“此处”。
1.3 BoardConfig.mk makefile
修改或添加政策文件和上下文的描述文件后,请更新您的 /device/manufacturer/device-name/BoardConfig.mk makefile 以引用 sepolicy 子目录和每个新的政策文件。 如需详细了解 BOARD_SEPOLICY 变量,请参阅 "system/sepolicy/README 文件"。
BOARD_SEPOLICY_DIRS += \<root>/device/manufacturer/device-name/sepolicyBOARD_SEPOLICY_UNION += \genfs_contexts \file_contexts \sepolicy.te
重新进行构建后,您的设备会启用 SELinux。现在,您可以根据您向 Android 操作系统添加的内容自定义 SELinux 政策(如下文“自定义 SELinux”章节中所述),也可以验证现有设置(如“验证 SELinux”中所述)。
在新政策文件和 BoardConfig.mk 更新部署到位后,新政策设置会自动内置到最终的内核政策文件中。如需详细了解如何在设备上构建 sepolicy,请参阅下面“构建 SELinux 政策”章节。
2. 实现
注意:AOSP 不再提供 audit2allow。请使用主机中的版本(Debian 和 Ubuntu 上的软件包“policycoreutils-python-utils”)。
如需开始使用 SELinux,请执行以下操作:
(1) 在内核中启用 SELinux:CONFIG_SECURITY_SELINUX=y
(2) 更改 kernel_cmdline 或 bootconfig 参数,以便:
BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
或
BOARD_BOOTCONFIG := androidboot.selinux=permissive
这仅适用于初始制定设备政策的情况。在拥有初始引导程序政策后,请移除此参数,以便将设备恢复强制模式,否则设备将无法通过 CTS 测试。
(3) 以宽容模式启动系统,看看在启动时会遇到哪些拒绝事件:
在 Ubuntu 14.04 或更高版本中,请运行以下命令:
adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
在 Ubuntu 12.04 中,请运行以下命令:
adb pull /sys/fs/selinux/policy
adb logcat -b all | audit2allow -p policy
(4) 评估警告输出,此类警告类似于 init: Warning! Service name needs a SELinux domain defined; please fix!。如需查看相关说明和工具,请参阅下面 “验证 SELinux” 章节。
(5) 标识设备以及需要添加标签的其他新文件。
(6) 为您的对象使用现有标签或新标签。查看 *_contexts 文件,了解之前是如何为内容添加标签的,然后根据对标签含义的了解分配一个新标签。这个标签最好是能够融入到政策中的现有标签,但有时也需要使用新标签,而且还需要提供关于访问该标签的规则。将您的标签添加到相应的上下文的描述文件中。
(7) 标识应该拥有自己的安全域的域/进程。您可能需要为每一项分别编写一个全新的政策。例如,从 init 衍生的所有服务都应该有自己的安全域。以下命令有助于查看保持运行的服务(不过所有服务都需要如此处理):
adb shell su -c ps -Z | grep init adb shell su -c dmesg | grep 'avc: '
(8) 查看 init.device.rc 以发现没有域类型的域。请在开发过程早期为其提供相应的域,以避免向 init 添加规则或将 init 访问权限与其自身政策中的访问权限混淆。
(9) 设置 BOARD_CONFIG.mk 以使用 BOARD_SEPOLICY_* 变量。如需详细了解如何进行此项设置,请参阅 system/sepolicy 中的 README。
(10) 检查 init.device.rc 和 fstab.device 文件,确保每一次使用 mount 都对应一个添加了适当标签的文件系统,或者指定了 context= mount 选项。
(11) 查看每个拒绝事件,并创建 SELinux 政策以妥善处理每个拒绝事件。请参阅下文“自定义 SELinux”章节中的示例。
建议从 AOSP 中的政策入手,然后在这些政策的基础上创建自己的自定义政策。如需详细了解政策策略以及其中一些步骤,请参阅下文 "编写 SELinux 政策" 章节。
3. 用例
下面列举了一些在开发软件以及制定关联的 SELinux 政策时需要注意的具体漏洞:
(1) 符号链接:由于符号链接以文件形式显示,因此系统通常将其作为文件进行读取,而这可能会导致漏洞。例如,某些特权组件(例如 init)会更改某些文件的权限,有时会使之极度开放。
这样一来,攻击者便可以将这些文件替换成指向其控制的代码的符号链接,从而重写任意文件。不过,如果您知道自己的应用绝不会遍历符号链接,则可以通过 SELinux 来禁止您的应用遍历符号链接。
(2) 系统文件:以应该只有系统服务器可以修改的一系列系统文件为例。由于 netd、init 和 vold 是以 root 身份运行的,因此它们也可以访问这些系统文件。这样一来,如果 netd 遭到入侵,这些文件乃至系统服务器本身都可能遭到入侵。
借助 SELinux,您可以将这些文件标识为系统服务器数据文件。这样一来,系统服务器就是唯一对这些文件具有读写权限的域。即使 netd 遭到入侵,它也无法将域切换到系统服务器域并访问这些系统文件,就算它是以 root 身份运行也是如此。
(3) 应用数据:另一个示例是必须以 root 身份运行但不应获得应用数据访问权限的一系列函数。这一项非常有用,因为它可以做出广泛的声明,例如禁止与应用数据无关的特定域访问网络。
(4) setattr:对于 chmod 和 chown 等命令,您可以标识关联域可以在哪些文件中进行 setattr 操作。这样一来,便可以禁止对这些文件之外的任何文件进行这类更改,即使以 root 身份进行也不例外。因此,应用可以对带 app_data_files 标签的文件运行 chmod 和 chown,但不能对带 shell_data_files 或 system_data_files 标签的文件运行这些命令。
四、自定义 SELinux
集成基本级别的 SELinux 功能并全面分析结果后,您可以添加自己的政策设置,以便涵盖对 Android 操作系统所做的自定义。这些政策必须仍然满足 Android 兼容性计划的要求,并且不得移除默认的 SELinux 设置。
制造商不得移除现有的 SELinux 政策####,否则可能会破坏 Android SELinux 实现及其管控的应用。这包括可能需要改进以遵守政策并正常运行的第三方应用。应用必须无需任何修改即可继续在启用了 SELinux 的设备上正常运行。
当开始自定义 SELinux 时,请注意:
(1) 为所有新的守护进程编写 SELinux 政策
(2) 尽可能使用预定义的域
(3) 为作为 init 服务衍生的所有进程分配域
(4) 在编写政策之前先熟悉相关的宏
(5) 向 AOSP 提交对核心政策进行的更改
同时,谨记下列禁忌:
(1) 不得创建不兼容的政策
(2) 不得允许对最终用户政策进行自定义
(3) 不得允许对移动设备管理 (MDM) 政策进行自定义
(4) 不得恐吓违反政策的用户
(5) 不得添加后门程序
如需查看具体要求,请参阅 Android 兼容性定义文档 中的“内核安全功能”部分。
SELinux 采用白名单方法,这意味着只能授予政策中明确允许的访问权限。由于 Android 的默认 SELinux 政策已经支持 Android 开源项目,因此您无需以任何方式修改 SELinux 设置。如果您要自定义 SELinux 设置,则应格外谨慎,以免破坏现有应用。如需使用此功能,请按下列步骤操作:
(1) 使用最新的 Android 内核。
(2) 采用最小权限原则。
(3) 仅针对您向 Android 添加的内容调整 SELinux 政策。默认政策能够自动适用于 Android 开源项目 代码库。
(4) 将各个软件组件拆分成多个负责执行单项任务的模块。
(5) 创建将这些任务与无关功能隔离开来的 SELinux 政策。
(6) 将这些政策放在 /device/manufacturer/device-name/sepolicy 目录中的 *.te 文件内(te 是 SELinux 政策源代码文件使用的扩展名),然后使用 BOARD_SEPOLICY 变量将它们纳入到您的 build 中。
(7) 先将新域设为宽容域。为此,可以在该域的 .te 文件中使用宽容声明。
(8) 分析结果并优化域定义。
(9) 当 userdebug build 中不再出现拒绝事件时,移除宽容声明。
完成 SELinux 政策更改的集成工作后,请在开发工作流程中添加一个步骤,以确保向前兼容 SELinux。在理想的软件开发过程中,SELinux 政策只会在软件模型发生变化时才需要更改,而不会在实际的实施方式变化时更改。
当您开始自定义 SELinux 时,首先要审核自己向 Android 添加的内容。如果添加的是执行新功能的组件,则在开启强制模式之前,您需要先确认该组件是否符合 Android 的安全政策,以及原始设备制造商 (OEM) 制定的所有相关政策。
为了防止出现不必要的问题,与其过度限制和不兼容,不如过度宽泛和过度兼容,因为前者会导致设备功能损坏。不过,如果您的更改能够惠及其他人,则应将这些更改作为补丁程序提交至默认 SELinux 政策。如果相应补丁程序已应用于默认安全政策,您将不需要针对每个新的 Android 版本进行此项更改。
1. 政策声明示例
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;
I: Android selinux中,是不是所有域都默认具有 domain.te 中指定的权限?
chatGPT: 并非所有域都默认具有 domain.te 中指定的权限。domain.te 是基础策略文件,主要定义通用规则(如 neverallow 限制)和核心权限模板,但具体域的权限需通过独立 .te 文件显式声明,且遵循「最小权限原则」和「默认拒绝」机制。
domain.te 是 SELinux 策略的基础框架,包含两类核心内容:
(1) neverallow 全局禁令:例如禁止普通域直接访问设备节点 neverallow { domain -init -ueventd -recovery } device:chr_file { open read write };,这类规则对所有未明确豁免的域生效。
(2) 基础权限模板:定义进程转换(transition)、继承(rlimitinh)等通用行为,但需其他域显式引用(如通过 init_daemon_domain(xxx) 宏初始化新域)。
关键结论:domain.te 不直接赋予权限,而是划定安全边界。任何域的具体操作权限(如文件读写、网络访问)必须在独立 .te 文件中单独声明。
典型误区:认为 domain.te 中的 allow domain self:capability { ... }; 会让所有域获得该能力,实际该规则仅对明确继承 domain 属性的域生效,且常被更具体的 neverallow 覆盖。
若未为服务定义域策略,系统会拒绝启动并提示 Service xxx does not have a SELinux domain defined. 例如在 init.rc 中声明服务但未创建 xxx.te,即使 domain.te 存在通用规则,该服务仍因缺乏上下文标签和权限定义而无法运行。
2. 政策示例
以下是一个完整的 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 读写数据。
在第二行中,DHCP 被声明为宽容域####。I: 可以先设置为宽容域测功能是否OK,然后再根据报错补权限。
在 init_daemon_domain(dhcp) 这一行中,该政策声明 DHCP 是从 init 衍生而来的,并且可以与其通信。I: 有init进程通过.rc文件启动的服务必须指定这个。
在 net_domain(dhcp) 这一行中,该政策允许 DHCP 使用 net 域中的常用网络功能,例如读取和写入 TCP 数据包、通过套接字进行通信,以及执行 DNS 请求。
在 allow dhcp proc_net:file write; 这一行中,该政策声明 DHCP 可以向 /proc 中的特定文件写入数据。这一行显示了 SELinux 的详细文件标签。它使用 proc_net 标签来限定 DHCP 仅对 /proc/sys/net 中的文件具有写入权限。
该示例的最后一部分以 allow dhcp netd:fd use; 开头,描述了允许应用之间如何交互。该政策声明 DHCP 和 netd 之间可通过文件描述符、FIFO 文件、数据报套接字以及 UNIX 信息流套接字进行通信。DHCP 只能向数据报套接字和 UNIX 信息流套接字中读写数据,但不能创建或打开此类套接字。
3. 可用控件
----------------------------------------------------------------------------------------------------- 类 | 权限 ----------------------------------------------------------------------------------------------------- 文件 | 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 ----------------------------------------------------------------------------------------------------- capabi- | chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable lity | 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 ----------------------------------------------------------------------------------------------------- 更多 | 还有更多 -----------------------------------------------------------------------------------------------------
4. neverallow 规则
SELinux neverallow 规则用于禁止在任何情况下都不应该发生的行为。 通过执行兼容性测试,现在各种设备上都会强制执行 SELinux neverallow 规则。
以下准则旨在协助制造商在自定义过程中避免出现与 neverallow 规则相关的错误。此处使用的规则编号与 Android 5.1 中使用的编号一致,并且会因版本而异。
规则 48:neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
请参阅 ptrace 的帮助页面。 sys_ptrace 权能用于授予对任何进程执行 ptrace 命令的权限,拥有该权限的组件能够对其他进程进行广泛的控制。只有该规则中列出的指定系统组件才能享有该权限。 如果需要该权能,则通常表明存在的某些内容不适用于面向用户的 build 或存在不需要的功能。请移除不必要的组件。
规则 76:neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
该规则旨在防止执行系统中的任意代码。具体来说,该规则声明仅执行 /system 中的代码,以便通过启动时验证等机制实现安全保证。通常,在遇到与 neverallow 规则相关的问题时,最好的解决办法是将违规代码移到 /system 分区。####
5. 在 Android 8.0 及更高版本中自定义 SEPolicy
此部分的指南适用于 Android 8.0 及更高版本中的供应商 SELinux 政策,包括有关 Android 开源项目 (AOSP) SEPolicy 和 SEPolicy 扩展的详细信息。如需详细了解 SELinux 政策如何在各分区和 Android 版本中保持兼容,请参阅下文 “政策兼容性” 章节。
6. 政策的存放位置
在 Android 7.0 及更低版本中,设备制造商可以将政策添加到 BOARD_SEPOLICY_DIRS,包括用来在不同设备类型之间增强 AOSP 政策的政策。在 Android 8.0 及更高版本中,将政策添加到 BOARD_SEPOLICY_DIRS 会将该政策仅存放在供应商映像中####。
在 Android 8.0 及更高版本中,政策位于 AOSP 中的以下位置:####
(1) system/sepolicy/public。其中包括所导出的用于供应商特定政策的政策。所有内容都会纳入 Android 8.0 兼容性基础架构。公共政策会保留在不同版本上,因此您可以在自定义政策的 /public 中添加任何内容。正因如此,可存放在 /public 中的政策类型的限制性更强。将此目录视为相应平台的已导出政策 API:处理 /system 与 /vendor 之间的接口的所有内容都位于这里。####
(2) system/sepolicy/private。包括系统映像正常运行所必需(但供应商映像政策应该不知道)的政策。
(3) system/sepolicy/vendor。包括位于 /vendor 但存在于核心平台树(非设备特定目录)中的组件的相关政策。这是构建系统区分设备和全局组件的软件工件;从概念上讲,这是下述设备专用政策的一部分。
(4) device/manufacturer/device-name/sepolicy。包含设备专用政策,以及对政策进行的设备自定义(在 Android 8.0 及更高版本中,该政策对应于供应商映像组件的相关政策)。
在 Android 11 及更高版本中,system_ext 和 product 分区还可以包含特定于分区的政策。system_ext 和 product 政策也分为公共政策和私有政策,且供应商可以使用 system_ext 和 product 的公共政策(例如系统政策)。
(1) SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS。包括所导出的用于供应商特定政策的政策。已安装到 system_ext 分区。
(2) SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS。包括 system_ext 映像正常运行所必需(但供应商映像政策应该不知道)的政策。已安装到 system_ext 分区。
(3) PRODUCT_PUBLIC_SEPOLICY_DIRS。包括所导出的用于供应商特定政策的政策。已安装到 product 分区。
(4) PRODUCT_PRIVATE_SEPOLICY_DIRS。包括 product 映像正常运行所必需(但供应商映像政策应该不知道)的政策。已安装到 product 分区。
注意:使用 GSI 时,系统不会装载 OEM 的 system_ext 和 product 分区。使用 OEM 的 system_ext 和 product 公共政策的供应商 sepolicy 中的规则变为 NOP,因为缺少 OEM 专用类型定义。
注意:在使用 system_ext 和 product 公共政策时要格外小心。公共政策充当 system_ext/product 和 vendor 之间的导出 API。合作伙伴应自行管理兼容性问题。
7. 支持的政策场景
在搭载 Android 8.0 及更高版本的设备上,供应商映像必须使用 OEM 系统映像和 Google 提供的参考 AOSP 系统映像(并在此参考映像上传递 CTS),这样可确保框架与供应商代码完全分离开来。此类设备支持以下场景。
7.1 仅含供应商映像的扩展
示例:从支持相关进程的供应商映像向 vndservicemanager 添加新服务。
与搭载旧版 Android 的设备一样,请在 device/manufacturer/device-name/sepolicy 中添加针对特定设备的自定义配置。管控供应商组件如何与其他供应商组件(仅限这些组件)交互的新政策应涉及仅存在于 device/manufacturer/device-name/sepolicy 中的类型。此处编写的政策允许运行供应商的代码,不会在仅针对框架的 OTA 期间更新,并且将存在于具有参考 AOSP 系统映像的设备上的组合政策中。
7.2 支持使用 AOSP 的供应商映像
示例:添加用于实现 AOSP 定义的 HAL 的新进程(通过供应商映像中的 hwservicemanager 注册)。
与搭载旧版 Android 的设备一样,请在 device/manufacturer/device-name/sepolicy 中执行针对特定设备的自定义配置。 作为 system/sepolicy/public/ 的一部分导出的政策可供使用,并且包含在供应商政策中。公共政策中的类型和属性可以用在新规则中,指示与新的供应商专用位的交互,但要遵守所提供的 neverallow 限制。与仅含供应商映像的情形一样,此处的新政策不会在仅针对框架的 OTA 期间更新,并且将存在于具有参考 AOSP 系统映像的设备上的组合政策中。
7.3 仅含系统映像的扩展
示例:添加一种仅供系统映像中的其他进程访问的新服务(通过 servicemanager 注册)。
将此政策添加到 system/sepolicy/private。您可以添加额外的进程或对象以在合作伙伴系统映像中启用功能,前提是这些新位不需要与供应商映像上的新组件互动(具体而言,即使没有供应商映像中的政策,此类进程或对象也必须能够完全正常运行)。system/sepolicy/public 导出的政策在此处的提供方式与仅含供应商映像的扩展相同。 此政策包含在系统映像中,可以在仅针对框架的 OTA 期间进行更新,但在使用参考 AOSP 系统映像时不会存在。
7.4 提供扩展 AOSP 组件的供应商映像扩展
示例:供同样存在于 AOSP 系统映像中的扩展客户端(例如扩展的 system_server)使用的新增非 AOSP HAL。
系统与供应商之间的交互政策必须纳入供应商分区上的 device/manufacturer/device-name/sepolicy 目录中。 这类似于上述添加供应商映像支持以使用参考 AOSP 映像的场景,不同之处在于修改后的 AOSP 组件可能还需要其他政策才能正确使用系统分区的其余部分(只要这些组件仍具有公开 AOSP 类型标签就可以)。
用于控制公开 AOSP 组件与仅含系统映像的扩展之间的交互的政策应该位于 system/sepolicy/private 中。
7.5 仅访问 AOSP 接口的系统映像扩展
示例:新的非 AOSP 系统进程必须访问 AOSP 所依赖的 HAL。
这与仅含系统映像的扩展示例类似,不同之处在于新的系统组件可能会通过 system/vendor 接口进行交互。针对新系统组件的政策必须位于 system/sepolicy/private,只要它是通过 AOSP 已在 system/sepolicy/public 中建立的接口发挥作用,就可以接受(即,该目录中包含相应功能所需的类型和属性)。虽然可以在设备专用政策中添加政策,但无法在仅针对框架的更新中使用其他 system/sepolicy/private 类型或进行更改(以任何影响政策的方式)。此政策可以在仅针对框架的 OTA 期间更改,但在使用 AOSP 系统映像时不会存在(也不会有新的系统组件)。
7.6 提供新系统组件的供应商映像扩展
示例:添加新的非 AOSP HAL 以供无需 AOSP 模拟的客户端进程使用(因此,该进程需要自己的域)。
与 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 政策中的对象添加标签。
8. 不受支持的政策场景
发布时搭载 Android 8.0 或更高版本的设备不支持以下政策场景和示例。
系统映像的其他扩展,这些扩展需要在仅支持框架的 OTA 之后获得新供应商映像组件的权限
示例:在下一个 Android 版本中添加新的非 AOSP 系统进程(需要自己的域),该进程需要访问新的非 AOSP HAL。
与新(非 AOSP)系统和供应商组件之间的交互类似,不同之处在于新的系统类型是在仅针对框架的 OTA 期间引入的。虽然这个新类型可以添加到 system/sepolicy/public 中的政策里,但现有的供应商政策不知道这个新类型,因为它仅跟踪 Android 8.0 系统公共政策。 AOSP 可通过某个属性(例如 hal_foo 属性)提供来自供应商的资源,进而处理此情况,但由于属性合作伙伴扩展在 system/sepolicy/public 中不受支持,因此供应商政策无法使用此方法。访问权限必须由之前存在的公共类型提供。
示例:对系统进程(AOSP 系统进程或非 AOSP 系统进程)的更改必须更改它与新的非 AOSP 供应商组件进行交互的方式。
在针对系统映像编写政策时,必须对具体的供应商自定义政策不知情####。因此,系统会通过 system/sepolicy/public 中的属性公开 AOSP 中涉及特定接口的政策,以便供应商政策可以选择启用将来使用这些属性的系统政策。不过,system/sepolicy/public 中的属性扩展不受支持,因此用于指示系统组件如何与新供应商组件交互的全部政策(这些政策不由 AOSP system/sepolicy/public 中已存在的属性进行处理)都必须位于 device/manufacturer/device-name/sepolicy 中。 这意味着系统类型无法在仅针对框架的 OTA 期间更改已为供应商类型授予的访问权限。
I: 好像多放在 vendor 下对编译失败来说更安全
六、构建 SELinux 政策
本页介绍了如何构建 SELinux 政策。SELinux 政策组合使用核心 AOSP 政策(平台)和设备专用政策(供应商)进行构建。从 Android 4.4 一直到 Android 7.0 的 SELinux 政策构建流程合并了所有 sepolicy fragment,然后在根目录中生成了整体文件。这意味着 SoC 供应商和 ODM 制造商每次修改政策时,都修改了 boot.img(针对非 A/B 设备)或 system.img(针对 A/B 设备)####。
在 Android 8.0 及更高版本中,平台政策和供应商政策是单独构建的。SoC 供应商和原始设备制造商 (OEM) 可以更新自己那部分政策####,构建自己的映像(例如 vendor.img 和 boot.img),然后独立于平台更新来更新这些映像。
不过,由于模块化的 SELinux 政策文件存储在 /vendor 分区中,因此 init 进程必须提早装载系统分区和供应商分区,以便能够从这些分区中读取 SELinux 文件,并将这些文件与系统目录中的核心 SELinux 文件合并(装载操作要在将这些文件加载到内核之前进行)。
1. 源文件
SELinux 的构建逻辑位于以下文件中:
external/selinux:外部 SELinux 项目,用于构建 HOST 命令行实用工具以编译 SELinux 政策和标签。
(1) external/selinux/libselinux:Android 仅使用外部 libselinux 项目的一个子集,以及一些 Android 专用自定义内容。如需了解详情,请参阅 external/selinux/README.android。
(2) external/selinux/libsepol:
chkcon:确定安全环境对指定的二进制政策(主机可执行文件)是否有效。
libsepol:用于操控二进制安全政策(主机静态/共享库、目标静态库)的 SELinux 库。
(3) external/selinux/checkpolicy:SELinux 政策编译器(主机可执行文件:checkpolicy、checkmodule 和 dispol)。依赖于 libsepol。
system/sepolicy:核心 Android SELinux 政策配置,包括上下文和政策文件。主要 sepolicy 构建逻辑也位于此处 (system/sepolicy/Android.mk)。
如需详细了解 system/sepolicy 中的文件,请参阅上文 “实现 SELinux” 章节。
2. Android 7.x 及更低版本
本部分介绍如何在 Android 7.x 及更低版本中构建 SELinux 政策。
2.1 适用于 Android 7.x 及更低版本的构建流程
SELinux 政策通过将核心 AOSP 政策与设备专用自定义政策合并而创建####。然后,系统会将合并后的政策传递给政策编译器和各种检查工具####。设备专用自定义政策通过在设备专用 Boardconfig.mk 文件中定义的 BOARD_SEPOLICY_DIRS 变量完成。该全局 build 变量包含一个用于指定其他政策文件搜索顺序的目录列表。
例如,SoC 供应商和 ODM 可以分别添加一个目录,一个用于 SoC 专用设置,另一个用于设备专用设置,以生成针对指定设备的最终 SELinux 配置:
(1) BOARD_SEPOLICY_DIRS += device/SOC/common/sepolicy
(2) BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy
system/sepolicy 和 BOARD_SEPOLICY_DIRS 中的 file_contexts 文件内容会串联在一起,以便在设备上生成 file_contexts.bin:

图 1. SELinux 构建逻辑。
sepolicy 文件由多个源文件组成:
(1) 纯文本 policy.conf 是通过依次串联 security_classes、initial_sids、*.te 文件、genfs_contexts 以及 port_contexts 而生成的。
I: policy.conf 可能就是所有配置最终生成的配置文本文件 #######
(2) 对于每个文件(例如 security_classes),其内容都是由 system/sepolicy/ 和 BOARD_SEPOLICY_DIRS 下的同名文件串联而成。####
(3) policy.conf 会被发送到 SELinux 编译器进行语法检查并被编译为二进制格式,从而生成设备上的 sepolicy。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/975050.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!