Calif 的安全研究人员演示了 OpenBSD 中的一个本地权限提升(LPE)漏洞,该漏洞源于一个近 40 年前的错误。该缺陷起源于原始的 BSD 源代码,其中共享内存连接计数被定义为有符号的 16 位 short 类型。由于该计数器是有符号的,反复 fork 带有共享内存连接记录的进程可能会使该值超过其 32,767 的最大限制,导致其回绕为负值。这种整数溢出与内核中一个独立的越界写入相结合,允许攻击者获得 root 权限。

这张图片代表了文章中描述的关于 OpenBSD 内核漏洞的主要研究项目。
该漏洞利用机制依赖于一系列复杂的操作,以绕过 KARL、SMAP 和 SMEP 等现代安全缓解措施。研究人员首先通过 fork 259 个进程,将共享内存连接计数回绕为负值(-32,643)。接着,他们进行堆整备(heap grooming),并利用 `sysctl(KERN_MALLOCSTATS)` 的指标来跟踪内存分配。通过在 `IPC_RMID` 操作期间赢得竞态条件,研究人员能够连接一个大小混淆的共享内存段。这触发了一个条件性的越界写入,覆盖了内核成员字段。最后,通过关闭一个用于遍历组成员的套接字,他们触发了原子递减操作,修改了页表项(PTE)的自引用映射,将其从用户可访问模式切换为主管可访问模式,从而允许执行内核代码。
虽然这些漏洞已在 OpenBSD errata 026 和 018 中得到修复,但研究人员强调了仍存在的若干架构风险。他们指出,虽然 OpenBSD 的 KARL 系统会随机化函数和数据的地址,但内核的内存分配器仍然是确定性的。这意味着早期启动的分配始终落在可预测的位置,使其成为覆盖函数指针(如 `lo0` 和 `enc0` ioctl 处理程序)的理想目标。为了缓解这些风险,研究人员提出了几项改进建议:实施“安全解链”(safe-unlinking)以检查双向链表的不变性,随机化自引用 PTE 映射的分配地址,或者通过随机化基地址和运行时分配顺序来使内核分配器变得非确定性。他们还指向了即将推出的编译器功能,例如“Alloc Tokens”,该功能可以将包含指针的分配与不包含指针的分配隔离,从而中和同类漏洞。