Linux ptrace 代码对调试寄存器 (debug registers) 的访问进行了虚拟化,而这段虚拟化代码存在错误的错误处理。这意味着,如果你向 DR0 等寄存器写入非法值,内核断点跟踪的内部状态可能变得损坏,尽管 ptrace() 调用会返回 -EINVAL。
例如,你可以在 x86 内核的 /proc/kallsyms 中找到 do_debug 的地址,然后将该地址传给附带的 PoC。我怀疑除 x86 之外的其他架构也可能受影响,但我尚未尝试利用此漏洞。该漏洞本身广泛分布于内核的通用代码和架构代码中。
我尚未发现利用此漏洞进行提权的明显途径,但可能存在。例如,使用此漏洞针对 perf NMI 处理程序 (perf NMI handler) 可能导致 NMI 栈溢出,进而引发各种形式的损坏。由于我只了解 x86 断点的工作原理,因此未尝试分析对非 x86 架构的影响,但该漏洞的影响可能大不相同。
Linus 主要在上游提交 f67b15037a7a50c57f72e69a6d59941ad90a0f0f 中修复了此问题。应用该提交后,错误处理仍然存在问题,但缺陷导致的结果是禁用断点而非不正确的断点。
http://man7.org/linux/man-pages/man2/ptrace.2.html
使用示例:
$ ./PoC.exe ffffffff81b44400