2014-08-20 51 views
15

强烈建议在创建64位内核(用于x86_64平台)时指示编译器不要使用用户空间ABI执行的128字节红色区域。 (对于GCC,编译器标志是-mno-red-zone)。为什么内核代码不能使用红色区域

如果内核被启用,内核将不会中断。

但是为什么呢?

+1

相关:http://stackoverflow.com/questions/38042188/where-exactly-is-the-red-zone-on-x86-64和http://stackoverflow.com/questions/37941779/why-do -we-need-stack-allocation-when-we-have-a-red-zone has answers answers that the red zone is about about for the code that can use it。 – 2016-06-26 22:24:01

回答

11

从AMD64 ABI引用:

128字节的区域以外的位置所指向的%RSP被认为是保留的,不受信号或中断处理程序进行修改。因此,函数可能会将此区域用于跨函数调用不需要的临时数据。特别是,叶函数可以在整个堆栈框架中使用这个区域,而不是在序言和尾声中调整堆栈指针。这个区域被称为红色区域。

从本质上讲,这是一个优化 - 用户级编译器知道到底有多少红色区域在任何给定时间使用(在最简单的实现,局部变量的整体尺寸),并可以在调用之前调整相应的%rsp一个子功能。

特别是在叶函数中,这可以产生一些性能优势,不需要调整%rsp,因为我们可以确定没有不熟悉的代码在函数中运行。 (POSIX信号处理程序可能被视为一种协同程序的形式,但您可以指示编译器在使用信号处理程序中的堆栈变量之前调整寄存器)。

在内核空间中,一旦开始考虑中断,如果这些中断对%rsp做出任何假设,那么它们可能是不正确的 - 关于红区的使用方面没有把握。所以,你要么假定它全部是脏的,并且不必要地浪费了堆栈空间(在每个函数中有效地运行一个128字节的保证局部变量),或者,你保证中断不会对%rsp做出假设 - 这很棘手。

在用户空间中,上下文切换+128字节的堆栈分配处理为您处理。

+5

这不仅节省空间。实际上不可能安全地实现正常的128字节的红区,因为在中断处理程序的任何代码运行之前,中断总是会破坏'%rsp'下面的16个字节。 – 2016-06-26 21:51:36

+0

@qdot,你能解释一下128字节的分配过程是什么意思吗?这意味着如果amd64 ABI没有“红区”的概念,最低的地址堆栈可能会增长128个字节? – 2016-09-19 05:09:19

8

在内核空间中,您正在使用中断使用的相同堆栈。发生中断时,the CPU pushes a return address and RFLAGS。这个破坏者低于rsp 16个字节。即使你想写一个中断处理程序,假设128个字节的红色区域是有价值的,那也是不可能的。


也许你可以有一个内核内部ABI认为有一个红色的小区从rsp-16rsp-48什么的。 (因为内核堆栈很小,而且大多数函数不需要非常多的红区)。

中断处理程序在推送任何寄存器之前必须先执行sub rsp, 32。 (并在iret之前将其恢复)。

运行sub rsp, 32之前,或者它的iret之前恢复rsp后,这种想法是行不通的如果中断处理程序本身可以被中断。在有价值的数据为rsp .. rsp-16时,会有一个漏洞窗口。


该方案的另一个实际问题是AFAIK gcc没有可配置的红区参数。它可以打开或关闭。所以如果你想利用它的话,你必须添加对红色区域的内核风格的支持到gcc/clang。

即使嵌套中断是安全的,好处是相当小的。证明在内核中安全的困难可能会使其不值得。 (正如我所说的,我不能肯定它可以安全地实现,因为我觉得嵌套中断是可能的。)


(顺便说一句,请参阅链接到ABI的标签维基记录了红区,和其他的东西。)

1

有可能使用红色区内核型环境。 IDTentry可以指定一个0..7的堆栈索引(ist),其中0有点特殊。 TSS包含这些堆栈的表格。 1..7被加载,并且用于由异常/中断保存的初始寄存器,并且不嵌套。如果按优先级划分各种异常条目(例如,NMI最高并且可以随时发生)并将这些堆栈视为蹦床,则可以安全地在内核类型上下文中处理红色区域。也就是说,在启用可能导致异常的中断或代码之前,您可以从保存的堆栈指针中减去128来获取可用的内核堆栈。

零指数堆叠相当于以更常规的方式,推入堆栈,国旗,PC,错误现有栈上时,有没有特权的过渡。

蹦床中的代码必须小心(duh,它是一个内核),它不会在生成其他异常的同时消除机器状态,而是提供一个很好的安全位置来检测病毒内核嵌套,堆栈损坏等... [抱歉,这么晚回应,注意到这一点,同时寻找别的东西]。

相关问题