【问题标题】:How does the linux kernel avoid the stack overwriting the text (instructions)?linux内核如何避免堆栈覆盖文本(指令)?
【发布时间】:2022-01-10 18:08:57
【问题描述】:

我很好奇内核如何防止堆栈变得太大,我发现this Q/A

问:Linux 内核如何强制堆栈大小限制?

A:由于虚拟内存,内核可以控制这一点。虚拟的 内存(也称为内存映射),基本上是一个虚拟列表 内存区域(基数 + 大小)和目标物理内存区域 内核可以操作每个程序所独有的。当一个 程序尝试访问不在此列表中的地址, 发生异常。此异常将导致上下文切换到 内核模式。内核可以查找故障。如果记忆是 生效,它将在程序可以之前就位 继续(例如,尚未从磁盘读取交换和 mmap)或 可以生成 SEGFAULT。

为了决定堆栈大小限制,内核简单地操作 虚拟内存映射。 - Stian Skjelstad

但我对这个答案不太满意。 “当程序试图访问不在此列表中的地址时,就会发生异常。” - 但是程序的文本部分(指令)不是虚拟内存映射的一部分吗?

【问题讨论】:

  • 作为一个关于术语的小问题:当我说“文本部分”时,它的字面意思是“来自基本程序指令的机器代码”,对吧?这是否包括来自共享内存(库)的代码,因为它们是由运行时链接器映射的?
  • .text 部分在普通用户空间进程中被映射为只读。并且在虚拟地址空间的另一端,因此在发生堆栈冲突之前有很多未使用的页面。 (其中一些页面故意未映射为堆栈增长区域下方的保护页面)。有关堆栈增长限制和其他内容的更多信息,请参阅 Linux process stack overrun by local variables (stack guarding)
  • 问题是关于内核(例如中断堆栈)还是关于用户程序?在任何情况下,内核都可以设置堆栈的限制(堆栈在 SS 段中,因此您可以设置不同的限制)。如果你超出限制,你会得到一个错误(或双重错误)
  • 你标记了这个 [linux-kernel];您是在谈论内核自己的堆栈吗? (实际上它使用每个任务的内核堆栈,至少用一个保护页分隔)。
  • @GiacomoCatenazzi:x86 Linux 不使用 SS 段限制,它使用分页。在长模式下,SS 段限制是硬连线到无限制,因为操作系统没有使用它,所以没有必要找到将其扩展到 64 位的方法。

标签: linux-kernel x86 stack-overflow stack-memory


【解决方案1】:

我问的是内核如何强制用户程序的堆栈大小。

有一个增长限制,用ulimit -s 设置主堆栈,这将阻止堆栈接近.text。 (如果堆栈溢出超过增长限制,下面的保护页面会确保存在段错误。)请参阅How is Stack memory allocated when using 'push' or 'sub' x86 instructions?。 (或者对于线程栈(不是主线程),栈内存只是一个正常的 mmap 分配,没有增长;唯一的惰性分配是物理页来支持虚拟内存。)

另外,.text 是可执行文件的读取+执行映射,因此如果不先调用mprotect,就无法修改它。 (这是一个私有映射,所以这样做只会影响内存中的页面,而不是实际文件。这就是文本重定位的工作方式:绝对地址的运行时修复,由动态链接器修复。)

限制增长的实际机制是简单地不扩展映射并在进程使用现有堆栈区域下方的堆栈指针触发硬件页面错误时分配新页面。 因此,页面错误是无效的,而不是正常堆栈增长情况下的软 aka 次要问题,因此交付了 SIGSEGV。


如果程序使用 alloca 或大小未经检查的 C99 VLA,恶意输入可能会使其跳过任何保护页面并进入其他读/写映射,例如 .data 或动态分配的内容。

为了强化有缺陷的代码,使其产生段错误而不是实际允许 堆栈冲突 攻击,有一些编译器选项可以让它随着堆栈的增长而触及每个中间页面,因此肯定会引发“绊线”以低于堆栈增长限制的未映射保护页的形式。见Linux process stack overrun by local variables (stack guarding)

如果您设置ulimit -s unlimited,您是否可以将堆栈扩展到其他映射,如果 Linux 在这种情况下确实允许无限增长,而无需在您接近另一个映射时保留保护页面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-17
    • 1970-01-01
    • 2019-05-30
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    • 2010-11-30
    相关资源
    最近更新 更多