这指的是CVE-2018-8897 (它似乎与CVE-2018-1087相关),描述如下:
在开发部分或全部操作系统内核时,“Intel 64和IA-32架构软件开发人员手册”(SDM)中的系统编程指南中的一项声明被错误处理,导致#DB异常出现意外行为,这些异常被MOV或POP SS延迟,例如,Windows、macOS、某些Xen配置或FreeBSD中的权限升级,或Linux内核崩溃。MOV到SS和POP SS指令抑制中断(包括NMI)、数据断点和单步陷阱异常,直到下一条指令之后的指令边界(SDM第3A卷;第6.8.3节)。(被抑制的数据断点是MOV访问到SS或POP到SS指令本身访问的内存上的数据断点。)注意,调试异常不会被中断启用(EFLAGS.IF)系统标志(SDMVol.3A;第2.3节)所抑制。如果MOV到SS或POP到SS指令后面的指令是SYSCALL、SYSENTER、INT 3等指令,在CPL <3时将控制转移到操作系统,则调试异常将在传输到CPL < 3之后传递。OS内核可能不会期望这种顺序的事件,因此可能会遇到意外的行为,当它发生。
在阅读这个相关的git提交到Linux内核。时,我注意到提交消息声明:
x86/ entry /64:不要将IST条目用于#BP堆栈 #BP/int3 3一点价值都没有。我们不允许在内核中的少数地方使用无效的堆栈在CPL0上运行k探针,32位内核永远使用#BP的正常中断门。 此外,在内核模式下,我们不允许在有用户的地方使用k探针,所以“偏执”也是不必要的。
鉴于该漏洞,我正在尝试理解提交消息中的最后一句话/段落。据我所知,IST条目是指中断堆栈表中的(据称)“已知的好”堆栈指针之一,可用于处理中断。我还了解到,#BP指的是断点异常(相当于INT3),而k探测是一种调试机制,声称只在内核中的环0 (CPL0)特权级别的几个地方运行。
但我在下一部分中完全迷失了方向,这可能是因为"usergs“是一个错误,而我只是忽略了原来的意图:
此外,在内核模式下,我们不允许在有用户的地方使用k探针,所以“偏执”也是不必要的。
这句话是什么意思?
发布于 2018-05-11 15:50:43
usergs指的是x86-64 swapgs指令,它将gs与内核内部保存的GS值交换,以便从syscall入口点找到内核堆栈。掉期还交换缓存的gsbase段信息,而不是基于gs值本身从GDT重新加载。(wrgsbase可以独立于GDT/LDT改变GS基)
AMD的设计是,syscall不会将RSP更改为指向内核堆栈,也不会读写任何内存,这样syscall本身就可以快速运行。但是,当您输入内核时,所有寄存器都保存着它们的用户空间值。有关2000年内核开发人员和AMD架构师之间邮件列表讨论的链接,请参阅为什么Windows64在x86-64上使用与所有其他OSes不同的调用约定?,对syscall和swapgs的设计进行调整,使其在出售任何AMD64 CPU之前都能使用。
显然,跟踪GS当前是内核还是用户值对于处理是很棘手的:没有办法说“我现在想要内核”;您必须知道是否在任何错误处理路径上运行swapgs。唯一的指令是交换,而不是将其设置为一个对另一个。
阅读arch/x86/entry/entry_64.S中的注释,例如64.S#L1267 (来自当前的Linux),其中提到了用户,下一个注释块描述了在使用内核gsbase进行错误处理代码之前执行swapgs。
IIRC,Linux内核[gs:0]持有一个线程信息块,位于该线程内核堆栈的最低地址。该块包含内核堆栈指针(作为绝对地址,而不是相对于gs)。
如果这个bug基本上是欺骗内核从用户控制的gsbase加载内核rsp,或者以其他方式搞砸了swapgs的错误计算,那么它在某个时候就有错误的gs,我也不会感到惊讶。
https://stackoverflow.com/questions/50286277
复制相似问题