SELinux 设置为默认拒绝,这意味着内核中具有钩子的每个访问都必须由政策显式允许。这意味着政策文件包含大量关于规则、类型、类、权限等信息。对 SELinux 的全面考虑超出了本文档的范围,但当启动新的 Android 设备时,了解如何编写政策规则现在至关重要。关于 SELinux 已经有很多可用的信息。有关建议的资源,请参阅支持文档。
关键文件
要启用 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 版本如何,您仍然在修改这些文件
政策文件
以 *.te
结尾的文件是 SELinux 政策源文件,用于定义域及其标签。您可能需要在 /device/manufacturer/device-name/sepolicy
中创建新的政策文件,但您应尽可能尝试更新现有文件。
上下文文件
上下文文件是您指定对象标签的位置。
file_contexts
将标签分配给文件,并由各种用户空间组件使用。当您创建新政策时,创建或更新此文件以将新标签分配给文件。要应用新的file_contexts
,请重建文件系统映像,或对要重新标记的文件运行restorecon
。在升级时,对file_contexts
的更改会自动应用于系统和 userdata 分区,作为升级的一部分。通过在分区以读写方式挂载后,将restorecon_recursive
调用添加到您的 init.board.rc 文件,也可以在升级时自动将更改应用于其他分区。genfs_contexts
将标签分配给文件系统(例如proc
或vfat
),这些文件系统不支持扩展属性。此配置作为内核政策的一部分加载,但更改可能不会对核心 inode 生效,这需要重新启动或卸载并重新挂载文件系统才能完全应用更改。也可以将特定标签分配给特定挂载,例如使用context=mount
选项的vfat
。property_contexts
将标签分配给 Android 系统属性,以控制哪些进程可以设置它们。此配置在启动期间由init
进程读取。service_contexts
将标签分配给 Android Binder 服务,以控制哪些进程可以为该服务添加(注册)和查找(查找)Binder 引用。此配置在启动期间由servicemanager
进程读取。seapp_contexts
将标签分配给应用进程和/data/data
目录。此配置在每次应用启动时由zygote
进程读取,并在启动期间由installd
读取。mac_permissions.xml
根据应用的签名以及可选的应用包名称,为应用分配seinfo
标记。seinfo
标记随后可用作seapp_contexts
文件中的键,以便为具有该seinfo
标记的所有应用分配特定标签。此配置在启动期间由system_server
读取。keystore2_key_contexts
将标签分配给 Keystore 2.0 命名空间。这些命名空间由 keystore2 守护进程强制执行。Keystore 始终提供基于 UID/AID 的命名空间。Keystore 2.0 还强制执行 sepolicy 定义的命名空间。有关此文件的格式和约定的详细说明,请参见此处。
BoardConfig.mk Makefile
在编辑或添加政策和上下文文件后,更新您的 /device/manufacturer/device-name/BoardConfig.mk
Makefile 以引用 sepolicy
子目录和每个新的政策文件。有关 BOARD_SEPOLICY
变量的更多信息,请参阅 system/sepolicy/README
文件。
BOARD_SEPOLICY_DIRS += \ <root>/device/manufacturer/device-name/sepolicy BOARD_SEPOLICY_UNION += \ genfs_contexts \ file_contexts \ sepolicy.te
重建后,您的设备将启用 SELinux。现在,您可以自定义您的 SELinux 政策,以适应您对 Android 操作系统所做的添加,如自定义中所述,或者验证您现有的设置,如验证中所述。
当新的政策文件和 BoardConfig.mk 更新到位后,新的政策设置将自动构建到最终的内核政策文件中。有关 sepolicy 如何在设备上构建的更多信息,请参阅构建 sepolicy。
实现
开始使用 SELinux
- 在内核中启用 SELinux:
CONFIG_SECURITY_SELINUX=y
- 更改 kernel_cmdline 或 bootconfig 参数,以便
或BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
这仅用于设备政策的初始开发。在您拥有初始引导程序政策后,请移除此参数,以便您的设备强制执行或未能通过 CTS。BOARD_BOOTCONFIG := androidboot.selinux=permissive
- 以 permissive 模式启动系统,并查看启动时遇到哪些拒绝
在 Ubuntu 14.04 或更高版本上 在 Ubuntu 12.04 上adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- 评估输出中类似
init: Warning! Service name needs a SELinux domain defined; please fix!
的警告。有关说明和工具,请参阅验证。 - 识别设备以及其他需要标记的新文件。
- 为您的对象使用现有标签或新标签。查看
*_contexts
文件,了解之前的事物是如何标记的,并利用标签含义的知识来分配新标签。理想情况下,这是一个适合政策的现有标签,但有时需要新标签,并且需要访问该标签的规则。将您的标签添加到相应的上下文文件中。 - 识别应具有自己的安全域的域/进程。您可能需要为每个域/进程编写全新的政策。例如,从
init
派生的所有服务都应具有自己的安全域。以下命令有助于揭示那些保持运行状态的服务(但所有服务都需要这样的处理)
adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- 查看
init.device.rc
以识别没有任何域类型的任何域。在您的开发过程早期为它们指定一个域,以避免将规则添加到init
,或者以其他方式将init
访问与它们自己的政策中的访问混淆。 - 设置
BOARD_CONFIG.mk
以使用BOARD_SEPOLICY_*
变量。有关设置此项的详细信息,请参阅system/sepolicy
中的 README。 - 检查 init.device.rc 和 fstab.device 文件,并确保每次使用
mount
都对应于正确标记的文件系统,或者指定了context= mount
选项。 - 检查每个拒绝并创建 SELinux 政策以正确处理每个拒绝。请参阅自定义中的示例。
您应该从 AOSP 中的政策开始,然后根据您自己的自定义项进行构建。有关政策策略以及更详细地了解其中一些步骤的更多信息,请参阅编写 SELinux 政策。
用例
以下是一些在制定您自己的软件和相关的 SELinux 政策时要考虑的具体漏洞示例
符号链接:由于符号链接显示为文件,因此它们通常被读取为文件,这可能会导致漏洞。例如,某些特权组件(例如 init
)会更改某些文件的权限,有时会变得过度开放。
攻击者可能会将这些文件替换为指向他们控制的代码的符号链接,从而允许攻击者覆盖任意文件。但是,如果您知道您的应用从不遍历符号链接,则可以使用 SELinux 禁止其这样做。
系统文件:考虑应仅由系统服务器修改的系统文件类。尽管如此,由于 netd
、init
和 vold
以 root 身份运行,因此它们可以访问这些系统文件。因此,如果 netd
受到攻击,它可能会破坏这些文件,并可能破坏系统服务器本身。
借助 SELinux,您可以将这些文件标识为系统服务器数据文件。因此,唯一具有对其进行读取/写入访问权限的域是系统服务器。即使 netd
受到攻击,它也无法将域切换到系统服务器域并访问这些系统文件,即使它以 root 身份运行。
应用数据:另一个示例是必须以 root 身份运行但不应访问应用数据的功能类。这非常有用,因为可以做出广泛的断言,例如禁止某些与应用数据无关的域访问互联网。
setattr:对于诸如 chmod
和 chown
之类的命令,您可以识别相关域可以在其中执行 setattr
的文件集。超出该范围的任何内容都可能被禁止进行这些更改,即使是 root 用户也不行。因此,应用可能会对标记为 app_data_files
的文件运行 chmod
和 chown
,但不会对 shell_data_files
或 system_data_files
运行。