Amo*_*mos 20 linux memory virtual-memory stack
操作系统是否为堆栈或其他东西保留了固定数量的有效虚拟空间?我是否能够仅通过使用大局部变量来产生堆栈溢出?
我写了一个小C程序来测试我的假设。它在 X86-64 CentOS 6.5 上运行。
#include <string.h>
#include <stdio.h>
int main()
{
int n = 10240 * 1024;
char a[n];
memset(a, 'x', n);
printf("%x\n%x\n", &a[0], &a[n-1]);
getchar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
运行程序给出&a[0] = f0ceabe0和&a[n-1] = f16eabdf
proc 映射显示堆栈: 7ffff0cea000-7ffff16ec000. (10248 * 1024B)
然后我尝试增加 n = 11240 * 1024
运行程序给出&a[0] = b6b36690和&a[n-1] = b763068f
proc 映射显示堆栈: 7fffb6b35000-7fffb7633000. (11256 * 1024B)
ulimit -s10240在我的电脑上打印。
如您所见,在这两种情况下,堆栈大小都大于ulimit -s给出的大小。并且堆栈随着更大的局部变量而增长。堆栈顶部以某种方式减少了 3-5kB &a[0](AFAIK,红色区域为 128B)。
那么这个堆栈映射是如何分配的呢?
vin*_*c17 16
似乎没有分配堆栈内存限制(无论如何,它不能无限堆栈)。https://www.kernel.org/doc/Documentation/vm/overcommit-accounting说:
C 语言堆栈增长执行隐式 mremap。如果您想要绝对保证并靠近边缘运行,您必须将堆栈映射为您认为需要的最大大小。对于典型的堆栈使用,这无关紧要,但如果您真的很在意,这是一个极端情况
然而,映射堆栈将是编译器的目标(如果它有一个选项)。
编辑:在 x84_64 Debian 机器上进行一些测试后,我发现堆栈在没有任何系统调用的情况下增长(根据strace)。所以,这意味着内核会自动增长它(这就是上面“隐式”的意思),即没有显式的mmap/mremap来自进程。
很难找到证实这一点的详细信息。我推荐Mel Gorman 的《理解 Linux 虚拟内存管理器》。我想答案在第 4.6.1 节处理页面错误中,除了“区域无效但位于像堆栈这样的可扩展区域旁边”和相应的操作“扩展区域并分配页面”。另见 D.5.2扩展堆栈。
关于 Linux 内存管理的其他参考资料(但几乎没有关于堆栈的内容):
编辑 2:此实现有一个缺点:在极端情况下,即使在堆栈大于限制的情况下,也可能无法检测到堆栈堆冲突!原因是对堆栈中变量的写入可能会在分配的堆内存中结束,在这种情况下,没有页面错误并且内核无法知道需要扩展堆栈。请参阅我在gcc-help 列表中开始的GNU/Linux 下的静默堆栈堆冲突讨论中的示例。为了避免这种情况,编译器需要在函数调用时添加一些代码;这可以通过-fstack-checkGCC完成(有关详细信息,请参阅 Ian Lance Taylor 的回复和 GCC 手册页)。
Linux 内核 4.2
rlim[RLIMIT_STACK]对应于 POSIXgerlimit(RLIMIT_STACK)acct_stack_growth最小的测试程序
然后我们可以使用最小的 NASM 64 位程序对其进行测试:
global _start
_start:
sub rsp, 0x7FF000
mov [rsp], rax
mov rax, 60
mov rdi, 0
syscall
Run Code Online (Sandbox Code Playgroud)
确保关闭 ASLR 并删除环境变量,因为它们会进入堆栈并占用空间:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
env -i ./main.out
Run Code Online (Sandbox Code Playgroud)
限制略低于我的ulimit -s(对我来说是8MiB)。看起来这是因为除了环境之外最初放置在堆栈上的额外 System V 指定数据:Linux 64 命令行参数在 Assembly | 堆栈溢出
如果您对此很认真,TODO 会制作一个最小的 initrd 映像,从堆栈顶部开始写入并下降,然后使用 QEMU + GDB 运行它。将 adprintf放在打印堆栈地址的循环上,并在acct_stack_growth. 这将是光荣的。
有关的: