标签: stack

堆栈分配在 Linux 中是如何工作的?

操作系统是否为堆栈或其他东西保留了固定数量的有效虚拟空间?我是否能够仅通过使用大局部变量来产生堆栈溢出?

我写了一个小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)。

那么这个堆栈映射是如何分配的呢?

linux memory virtual-memory stack

20
推荐指数
2
解决办法
2万
查看次数

什么设置 fs:[0x28](堆栈金丝雀)?

这篇文章可以看出这FS:[0x28]是一个堆栈金丝雀。我在这个函数上使用 GCC 生成相同的代码,

void foo () {
    char a[500] = {};
    printf("%s", a);
}
Run Code Online (Sandbox Code Playgroud)

具体来说,我得到这个程序集..

    0x000006b5      64488b042528.  mov rax, qword fs:[0x28]                ; [0x28:8]=0x1978 ; '(' ; "x\x19"
    0x000006be      488945f8       mov qword [local_8h], rax
...stuff...
    0x00000700      488b45f8       mov rax, qword [local_8h]
    0x00000704      644833042528.  xor rax, qword fs:[0x28]
    0x0000070d      7405           je 0x714
    0x0000070f      e85cfeffff     call sym.imp.__stack_chk_fail           ; void __stack_chk_fail(void)
    ; CODE XREF from 0x0000070d (sym.foo)
    0x00000714      c9             leave
    0x00000715      c3             ret
Run Code Online (Sandbox Code Playgroud)

什么是设置值fs:[0x28]?内核,还是 GCC 投入了代码?你能在内核中显示代码,或者编译成设置的二进制文件fs:[0x28]吗?金丝雀是在启动时重新生成的,还是在进程生成时重新生成的?这是在哪里记录的?

linux security gcc stack

20
推荐指数
2
解决办法
5480
查看次数

为什么在现代 Linux 上,默认堆栈大小如此之大 - 8MB(在某些发行版上甚至是 10)

例如,在 OSX 上,它甚至小于 512k。

考虑到应用程序不使用递归并且不分配大量堆栈变量,是否有任何推荐的大小?
我知道这个问题太广泛了,它在很大程度上取决于使用情况,但仍然想问,因为我想知道这个庞大的数字背后是否有一些隐藏的/内部/系统原因


我想知道,因为我打算在我的应用程序中将堆栈大小更改为 512 KiB - 这听起来仍然是一个巨大的数字,但它比 8MiB 小得多 - 并且会导致进程的虚拟内存显着减少,因为我有很多线程(I/O)。

我也知道这并没有什么坏处,这里有很好的解释pthreads 的默认堆栈大小

linux osx virtual-memory multithreading stack

13
推荐指数
2
解决办法
8999
查看次数

如何监控每个进程/每个线程的内存消耗(分为堆、堆栈、数据、代码)?

在开始编写自己的代码之前,我想知道是否有 GNU/Linux 软件能够输出类似于QNX 的showmem.

对于正在运行的每个进程的每个线程,我希望看到内存消耗分为以下几类:

 Process listing (Total, Code, Data, Heap, Stack, Other)
 319488  1024000      24587     167936      24576          0        4103 devc-con-hid (thread 2)
    0          0          0          0       4096          0        4103 devc-con-hid (thread 2)
    0          0          0          0      20480          0        4103 devc-con-hid (thread 1)
    0     102400       8192          0          0          0        4103 devc-con-hid (proc/boot/devc-con-hid)
    0          0      16384          0          0          0        4103 devc-con-hid (proc/boot/libc.so.3)
    0          0          0          0          0  (   36864)       4103 devc-con-hid (/dev/mem)
Run Code Online (Sandbox Code Playgroud)

有什么可以使这成为可能吗?

linux memory stack

11
推荐指数
1
解决办法
2万
查看次数

ELF 加载器如何确定初始堆栈大小?

我正在研究 ELF 规范(http://www.skyfree.org/linux/references/ELF_Format.pdf),关于程序加载过程我不清楚的一点是堆栈是如何初始化的,以及什么初始页面大小是。这是测试(在 Ubuntu x86-64 上):

$ cat test.s
.text
  .global _start
_start:
  mov $0x3c,%eax
  mov $0,%edi
  syscall
$ as test.s -o test.o && ld test.o
$ gdb a.out -q
Reading symbols from a.out...(no debugging symbols found)...done.
(gdb) b _start
Breakpoint 1 at 0x400078
(gdb) run
Starting program: ~/a.out 

Breakpoint 1, 0x0000000000400078 in _start ()
(gdb) print $sp
$1 = (void *) 0x7fffffffdf00
(gdb) info proc map
process 20062
Mapped address spaces:

          Start Addr           End Addr       Size     Offset …
Run Code Online (Sandbox Code Playgroud)

memory elf x86 linux-kernel stack

10
推荐指数
1
解决办法
2145
查看次数

为什么 bash 的 tab 补全会触发堆栈保护器?

我在 Manjaro 上使用bash5.0.16(和bash-completion2.10)。今天,我在移动一些文件时心不在焉地按了 Tab 键,并收到了一条意想不到的消息:

[charles@wirepile some_dir]$ mv ~down*** stack smashing detected ***: <unknown> terminated
Run Code Online (Sandbox Code Playgroud)

我必须^C重新获得对外壳的控制。

看来,每当在波浪号字符上调用制表符补全(无论后面有或没有其他字符)时,我的(最新的 Manjaro)bash 版本都会触发堆栈保护器。以下确实有效:

[charles@wirepile some_dir]$ ls ~/
.this_dir/                .that_file                 another_file
Run Code Online (Sandbox Code Playgroud)

我的 中不应该有任何不寻常的行.bashrc,除非 Manjaro 默认自定义它。

我想这是某种缓冲区溢出,应该被视为一个错误——这是故意的吗?我应该联系开发人员还是包维护人员?

我也很好奇——有人能重现这个问题吗?

bash gcc stack

5
推荐指数
1
解决办法
263
查看次数

Linux 中的内存随机化

我创建了一个简单的 C 程序,每次在 GDB 中加载它时,我都会看到分配给程序指令的相同内存地址。例如,一个函数what()总是在内存位置 0x000055555555472d 加载。实际上,每次执行的堆栈都完全相同(不仅是堆栈的内容,还包括 rsp 指向的内存地址。

我知道可以通过将“/proc/sys/kernel/randomize_va_space”设置为 0 在 Linux 中禁用 ASLR,但我的 Debian 系统中的值为 2。

root@Sierra ~ % cat /proc/sys/kernel/randomize_va_space 
2
Run Code Online (Sandbox Code Playgroud)

根据我对 ASLR 的理解,这些地址应该在每次运行时随机化。我的问题是为什么会发生这种情况?我做错了什么吗?

memory stack aslr

4
推荐指数
1
解决办法
809
查看次数

为什么克隆包装器需要堆栈参数?

我一直在仔细阅读 clone() 的 linux 手册页,我了解 clone() 包装器和“原始”系统调用之间的区别。但我不明白的是为什么父进程需要为子进程分配一个堆栈,即使包装器中没有使用 CLONE_VM。

如果不使用 CLONE_VM,包装器是否会简单地忽略堆栈参数?为什么需要它呢?原始系统调用允许它为空,这是有道理的,但我不明白为什么包装器需要这个。即使您不告诉它,包装器也会让孩子和父母共享内存吗?

linux system-calls stack clone

4
推荐指数
1
解决办法
284
查看次数

使用 pthread 无限堆栈大小

我的默认堆栈大小(根据 ulimit -s)是 8192 kB,所以当我尝试运行它时,自然会出现段错误下面的代码。此外,自然地,如果我执行'ulimit -s 9000',它可以正常工作。但是,当我执行 'ulimit -s unlimited' 时,代码再次出现段错误。任何想法这里发生了什么?

如果有用,我正在使用内核 4.19.0-6 和 gcc 版本 Debian 8.3.0-6 运行 Debian 10。

#include <iostream>
#include <unistd.h>
#include <cstdlib>

void* wait_exit(void*)
{
  char bob[8193*1024];
  return 0;
}

int main()
{
  pthread_t t_exit;
  int ret;
  
  if((ret = pthread_create(&t_exit,NULL,wait_exit,NULL)) !=0)
  {
    std::cout<<"Cannot create exit thread: "<<ret<<std::endl;
  }
  std::cout<<"Made thread"<<std::endl;
  sleep(5);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

segmentation-fault stack pthreads

3
推荐指数
1
解决办法
198
查看次数

为什么堆栈 VMA 必须是可执行的?

我目前正在阅读Robert Love 的Linux Kernel Development

在“15 进程地址空间”一章中,他打印了进程的内存映射。

user@machine:~$ pmap 1424
#all the processes mapped memory (skipped for readability)
bfffe000 (8KB)        rwxp (0:00 0)         [ stack ]
Run Code Online (Sandbox Code Playgroud)

最后一行显示堆栈(随着它向下增长)。
他现在说:

堆栈自然是可读、可写和可执行的——否则没有多大用处。

据我所知,我们将堆栈用于数据和代码地址(函数及其参数/变量)。

我不明白为什么堆栈必须是可执行的?

process kernel memory stack

2
推荐指数
1
解决办法
527
查看次数

Unix 操作系统上与堆栈相关的文件在哪里?

我在我的一台计算机上运行 Arch Linux,64 位最新更新。我目前是一名计算机科学专业的学生,​​昨天我们进行了一项测试,我们将使用链表实现动态堆栈。我现在有兴趣了解我的计算机中的堆栈是如何构建的,但是我无法在我的 Arch Linux 计算机上找到任何带有注释的“stack.c”。堆栈编程位于何处?我了解堆栈如何创建内存,但我想实际查看代码并可能自己玩弄它。

c arch-linux linux-kernel stack

0
推荐指数
1
解决办法
94
查看次数