SELinux 设为了“默认拒绝”模式,也就是说,对于在内核中存在钩子的每一次访问,都必须获得政策的明确许可。这意味着政策文件中包含规则、类型、类、权限等方面的大量信息。关于 SELinux 的完整注意事项不在本文档的讨论范围之内,现在您必须要了解的是在启动新的 Android 设备时如何编写政策规则。目前有大量关于 SELinux 的信息可供您参考。关于建议的资源,请参阅支持文档。
下面简要总结了在 Android 设备上实现 SELinux 时需要执行的步骤:
init
启动的每项服务(进程或守护进程)分配专用的域。
dmesg
输出中以下形式的警告:“init: Warning! Service name needs a SELinux domain defined; please fix!”(init:警告!服务名称需要一个已定义的 SELinux 域;请更正!)。
ps -Z | grep init
输出,看看哪些服务正在 init 域中运行。
原始设备制造商 (OEM) 最好从 AOSP 中的政策入手,然后在这些政策的基础上创建自己的自定义政策。
SELinux for Android 随附了立即启用 SELinux 所需的一切。您只需集成最新的 Android 内核,然后整合 system/sepolicy 目录中的文件即可:
https://android.googlesource.com/kernel/common/
https://android.googlesource.com/platform/system/sepolicy/
这些文件在编译后会包含 SELinux 内核安全政策,并涵盖上游 Android 操作系统。您应该不需要直接修改 system/sepolicy 中的文件,而只需添加您自己的设备专用政策文件(位于 /device/manufacturer/device-name/sepolicy 目录中)即可。
要实现 SELinux,您必须创建或修改以下文件:
重要提示:请勿更改 Android 开放源代码项目提供的 app.te 文件,否则可能会破坏所有第三方应用。
restorecon
。在升级时,对 file_contexts 所做的更改会在升级过程中自动应用于系统和用户数据分区。此外,还可以通过以下方式使这些更改在升级过程中自动应用于其他分区:在以允许读写的方式装载相应分区后,将 restorecon_recursive 调用添加到 init.board.rc 文件中。
接下来,只需在 sepolicy 子目录和各个政策文件创建之后,更新 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
注意:从 M 版开始已不再需要 BOARD_SEPOLICY_UNION,因为 BOARD_SEPOLICY_DIRS 变量中包含的任何目录内的所有政策文件都会与基本政策自动合并。
设备在重新编译后会启用 SELinux。现在,您可以根据自己向 Android 操作系统添加的内容自定义自己的 SELinux 政策(如自定义中所述),也可以验证您的现有设置(如验证中所述)。
在新政策文件和 BoardConfig.mk 更新部署到位后,新政策设置会立即自动内置到最终的内核政策文件中。
下面列举了一些在开发软件以及制定关联的 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 标签的文件运行这些命令。
下面详细介绍了 Android 建议您如何采用并自定义 SELinux 来保护设备:
CONFIG_SECURITY_SELINUX=y
BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
。
adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/board/root/sepolicy
adb shell su -c dmesg | grep denied | audit2allow
init
衍生的所有服务都应该有自己的安全域。可以通过以下命令查看保持运行的服务(不过所有服务都需要如此处理):$ adb shell su -c ps -Z | grep init
$ adb shell su -c dmesg | grep 'avc: '
init
访问权限与其自身政策中的访问权限混淆。
BOARD_CONFIG.mk
设为使用 BOARD_SEPOLICY_*
变量。如需关于如何进行此项设置的详细信息,请参阅 system/sepolicy 中的 README。