内核提供的重要安全功能之一是以地址空间分离的形式为用户空间进程提供内存保护。不同于用户空间进程,内核中的各项任务都在同一个地址空间内运行,内核中任意位置上的漏洞都可能会影响系统内存中与其无关的部分。内核的内存保护机制设计用于在存在漏洞的情况下仍能保持内核的完整性。
1. 将内存标记为只读/不可执行
该功能将内核内存划分为多个逻辑区段,并限定每个区段的页访问权限。将代码标记为只读可执行。将数据区段标记为不可执行,并进一步将其细分为只读区段和读写区段。该功能通过配置选项 CONFIG_DEBUG_RODATA 启用。
该功能是由 Kees Cook 汇集 Grsecurity 中的 KERNEXEC 部分功能(由 Brad Spengler 实现)和 Qualcomm 的 CONFIG_STRICT_MEMORY_RWX 部分功能(由 Larry Bassel 和 Laura Abbott 合作实现)而实现的。位于 arm/arm64 上游内核的 CONFIG_DEBUG_RODATA 已向后移植到 Android 的 3.18+ arm/arm64 通用内核。
2. 限制内核对用户空间的访问
该功能通过阻止内核直接访问用户空间内存来增强对内核的保护。这样可以增大许多攻击的难度,这是因为攻击者对于可执行的内核内存(特别是启用 CONFIG_DEBUG_RODATA 的内存)的控制力要弱得多。
类似的功能已经存在,Grsecurity 的 UDEREF 最早提供了此项功能。该功能通过配置选项 CONFIG_CPU_SW_DOMAIN_PAN 启用,由 Russell King 完成了该功能的 ARMv7 实现,并由 Russell King 向后移植到 Android 4.1 内核。
3. 增强对堆叠缓冲区的溢出保护
与其前身 stack-protector 非常类似,stack-protector-strong 不但可以防止系统出现堆叠缓冲区溢出,还额外提供对更多数组类型的保护,而其前身仅保护字符型数组。Stack-protector-strong 由 Han Shan 实现并添加到 gcc 4.9 编译器。