内核加固

Android 8.0 增添了内核加固功能,以帮助减少内核漏洞并发现内核驱动程序中的错误。这些功能位于分支 android-3.18、android-4.4 和 android-4.9 的 kernel/common 中。

实现

要获得这些功能,设备制造商和 SOC 应该将来自 kernel/common 的所有加固补丁程序合并到其内核树并启用以下内核配置选项:

  • 加固后的用户复制功能:CONFIG_HARDENED_USERCOPY=y
  • PAN 模拟 - arm64:CONFIG_ARM64_SW_TTBR0_PAN=y
  • PAN 模拟 - arm:CONFIG_CPU_SW_DOMAIN_PAN=y
  • KASLR - 4.4 及更高版本的内核:CONFIG_RANDOMIZE_BASE=y

KASLR 还需要引导加载程序支持以通过设备树节点 /chosen/kaslr-seed 或通过实现 EFI_RNG_PROTOCOL 来传递硬件熵。

此外,还要确保启用现有的加固功能:

  • 堆栈缓冲区溢出缓解:CONFIG_CC_STACKPROTECTOR_STRONG=y
  • 内存储器保护:CONFIG_DEBUG_RODATA=yCONFIG_STRICT_KERNEL_RWX=y
  • 限制内核对用户空间的访问 - x86(默认已启用):CONFIG_X86_SMAP=y

测试

要测试您的实现,请将 CONFIG_LKDTM=y 添加到内核配置,并确认以下每个命令都会导致内核崩溃:

echo ACCESS_USERSPACE > /sys/kernel/debug/provoke-crash/DIRECT
echo EXEC_USERSPACE > /sys/kernel/debug/provoke-crash/DIRECT
echo WRITE_RO > /sys/kernel/debug/provoke-crash/DIRECT
echo WRITE_RO_AFTER_INIT > /sys/kernel/debug/provoke-crash/DIRECT
echo WRITE_KERN > /sys/kernel/debug/provoke-crash/DIRECT
echo EXEC_STACK > /sys/kernel/debug/provoke-crash/DIRECT
echo EXEC_RODATA > /sys/kernel/debug/provoke-crash/DIRECT
echo EXEC_KMALLOC > /sys/kernel/debug/provoke-crash/DIRECT
echo EXEC_VMALLOC > /sys/kernel/debug/provoke-crash/DIRECT
echo CORRUPT_STACK > /sys/kernel/debug/provoke-crash/DIRECT

对于 android-4.9:

echo USERCOPY_HEAP_SIZE_TO > /sys/kernel/debug/provoke-crash/DIRECT
echo USERCOPY_HEAP_SIZE_FROM > /sys/kernel/debug/provoke-crash/DIRECT

常见问题

这些更改可能会暴露内核驱动程序中的错误,这些错误则需要由设备制造商或内核驱动程序所有者修复。

  • 将数据复制到用户空间/从用户空间复制数据时,加固用户复制功能会发生错误的边界检查。应该像修复任何其他存储器损坏错误一样,对这些错误进行修复。
  • PAN 模拟会导致内核直接访问用户空间,而这是不允许的。相反,尝试访问用户空间存储器的驱动程序需要改为使用标准的 copy_to_user()/copy_from_user() 函数。