可以使用哪些硬件或软件解决方案来防止堆栈溢出?
防止堆栈溢出的硬件解决方案是什么? 例如,当我们要设计一个新的操作系统时,如何防止堆栈溢出?
谢谢
What is the hardware solution for prevention of stack overflow?
For example, when we want to design a new operating system, how can we prevent stack overflows?
Thank you
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果可以静态确认代码不具有任何直接或间接递归,则静态分析可以得出最坏情况的堆栈使用情况。确保堆栈足够大并且不会出现堆栈溢出。最大的困难是可能很难确定哪些函数可以被哪些函数指针调用。例如,如果一个函数指针可以指向 foo1() 或 foo2(),另一个函数指针可以指向 bar1() 或 bar2(),并且 foo1() 调用第二个函数指针(从而到达 bar1 或 bar2),则不会有递归的可能性,但如果编译器无法确定第二个指针只能指向 bar1() 或 bar2() 它可能不知道这一点。
如果可以确定应用程序是非递归的,并且静态分析最坏情况调用图并不比实际发生的情况差太多,则可以完全避免堆栈并静态分配所有变量。在某些情况下(特别是在没有高效索引的体系结构上),与使用堆栈相比,这种方法可能会显着提高性能。
从安全角度来看,避免堆栈/缓冲区溢出漏洞的一个好方法是避免将真实的程序计数器地址存储在“普通”指针可以访问的任何地方。将程序计数器堆栈与参数/自动变量堆栈完全分开存储,并且不直接存储任何函数指针。相反,让每个“函数指针”成为具有相同签名的函数表的索引,并在使用索引之前检查索引以确保其在范围内;如果两组或多组函数具有不同的安全含义,并且应该由完全不同的指针调用,请根据需要调整一组的签名以使其与另一组不同(因此不能调用第一组中的函数)转换为对第二个函数的调用)。
If code can be statically confirmed not to have any direct or indirect recursion, static analysis can yield a worst-case stack usage. Make sure the stack is big enough and there won't be any stack overflow. The biggest difficulty is that it may be hard to determine which functions can be called by which function pointers. For example, if one function pointer can point to foo1() or foo2(), another can point to bar1() or bar2(), and foo1() calls the second function pointer (thus reaching bar1 or bar2) there would be no possibility of recursion, but if the compiler can't determine that the second pointer can only point to bar1() or bar2() it might not know that.
If an application can be determined to be non-recursive, and if the static-analysis worst-case call-graph isn't too much worse than what can actually happen, it may be possible to avoid the stack entirely and allocate all variables statically. In some cases (especially on architectures without efficient indexing) this approach may substantially improve performance compared with using a stack.
From a security standpoint, a good means of avoiding stack/buffer overflow exploits is to avoid storing real program-counter addresses anywhere that "normal" pointers can access. Store the program-counter stack entirely separately from the parameter/auto-variable stack, and don't store any function pointers directly. Instead have every "function pointer" be an index into a table of functions having the same signature, and check the index to ensure it's in range before using it; if two or more groups of functions have different security implications and should be called by completely different pointers, tweak the signature of one group if needed to make it different from the other (so a calls to a function in the first group can't be converted to a call to a function in the second).
哈佛架构提供了一些针对堆栈溢出攻击的保护。 哈佛架构计算机是否能够免受任意代码注入和执行攻击?
但是,在操作系统级别,您可能需要考虑使用
The Harvard Architecture provides some protection from stack overflow attacks. Are Harvard architecture computers immune to arbitrary code injection and execution attacks?
But, at the OS level you might want to consider having a non-executable stack.
您可能会感到惊讶,但其中一个选项是无堆栈硬件架构(真实的或模拟的)(此处讨论)。显然,没有堆栈 - 没有堆栈溢出。
You may be surprised, but one of the options is stackless hardware architecture (either real or emulated) (discussed here). Apparently, no stack - no stack overflows.
当堆栈处于预定义阈值时,某些微控制器会提供硬件陷阱。这可以用于正常关闭,或者将堆栈分页到外部 RAM 并重新启动。有一个类似的“下溢”陷阱可以将旧堆栈重新分页。
Some microcontrollers provide for a hardware trap when the stack is at a predefined threshold. This can either be used to shutdown gracefully, or to page the stack out to external RAM and start afresh. There's a similar "underflow" trap to page the old stack back in.