c - 了解 C 中的堆栈溢出处理
问题描述
我很好奇如何在 C 中捕获堆栈溢出并偶然发现GNU libsigseg 库。
这个库可以在很多平台上捕获堆栈溢出并提供一个实现示例。
为了使用该库安装堆栈溢出侦听器,必须首先为备用堆栈保留一些空间。据我了解,这个备用堆栈用于运行侦听器,因为真正的堆栈不可用。
备用堆栈保留在altstack.h(第 40 行)中,如下所示:
[][ ][ ][ ]
| | | |
| | | crumple_zone (8 KiB)
| | usable_space (16 KiB)
| crumple_zone (8 KiB)
offset (31 B)
可用空间是实际使用的空间,而折叠区域的存在是为了防止备用堆栈上的溢出:如果溢出,它会进入分配的空间,防止出现段错误,并且可能有时间检测到它。
但,
- 我不明白为什么在堆栈之前和之后会有一个折叠区;堆栈只向一个方向增长。是不是因为某些平台的堆栈朝一个方向增长,而其他平台的堆栈朝另一个方向增长?
- 我不明白为什么会有偏移量。
以下是作者给出的解释:
glibc 说:用户应该使用 SIGSTKSZ 作为用户提供的缓冲区的大小。我们希望以一种比崩溃更好的方式检测备用堆栈的堆栈溢出,因此与我们处理 libsigsegv 相比,我们过度分配。此外,我们有意交出一个未对齐的指针,以确保备用堆栈最终仍然对齐。
最后一条语句让我有点不知所措:“......我们故意提交一个未对齐的指针,以确保备用堆栈仍然对齐”。如果我们使堆栈不对齐,堆栈如何最终对齐?
解决方案
我不明白为什么在堆栈之前和之后会有一个折叠区;
堆栈被声明为全局char mystack_storage[...]
。
假设堆栈向下增长,您需要存储低端的折叠区域来检测备用堆栈本身的溢出。
问题:数组mystack_storage[]
后面是什么?
答:你不知道。
如果紧随其后有另一个数组怎么办,如果该数组超出范围(例如用类似的东西other_array[-20] = 'a';
)怎么办?
要检测这种下溢,您还需要另一端的折叠区。
如果我们使堆栈不对齐,堆栈如何最终对齐?
mystack
指针故意错位。如果它直接用作备用堆栈,它将违反许多平台上的堆栈对齐要求,并且很可能会导致崩溃。
为了防止这种情况,库不能mystack
直接使用,而是在其他地方对齐。
您指向的代码旨在测试其他代码是否正常工作。
更新:
我仍然不明白偏移量。如果不使用偏移量,为什么 mystack 指针会违反堆栈对齐要求?
没有偏移,mystack
的对齐方式是未知的。它可能恰好在 16 字节、8 字节甚至 1 字节边界上对齐。
有了偏移量,就可以保证不对齐(在 1 字节边界上对齐)。
为什么不是相反:通过添加偏移量,它会故意错位并违反堆栈对齐要求。
是的,指针是故意错位的。
关键是:实际使用 mystack
的代码(该代码在别处,我没有寻找它)已经准备好mystack
通过正确对齐来处理 misaligned (我们称之为“对齐代码”)。您指向的代码旨在练习其他“对齐代码”。
现在,那个“对齐代码”在哪里?
我以为它在图书馆的其他地方,但我错了。此处直接使用未对齐的mystack
指针。
那么谁在进行所需的对齐呢?内核可以!
来自man sigaltstack
:
ss.ss_sp
This field specifies the starting address of the stack. When a signal
handler is invoked on the alternate stack, the kernel automatically
aligns the address given in ss.ss_sp to a suitable address boundary
for the underlying hardware architecture.
mystack
因此,未对齐旨在执行的“其他代码”不在库中,而是在内核中。
推荐阅读
- python - 在多个 python 文件中使用单个弹性搜索连接对象?
- python - 尝试在 Python 中使用 Panda 的“loc”函数估算缺失值时出错
- ios - 如何在iOS中快速显示多个标记的标记标题而不点击它,就像iOS照片库中的地方一样
- python - ElementTree - 将子元素附加到元素的问题
- outlook-addin - Outlook .. 如何过滤对话 ID 上的邮件?
- python - 如何解决类型双精度的无效输入语法
- java - 无法使用 java 在 Minio 中上传 1 GB 文件?
- javascript - React native:迭代 JSON 对象而不获取未定义的函数
- ios - 如何在通知内容扩展中单击按钮上打开两个特定的视图控制器?
- ios - 没有这样的模块'ParseFacebookUtilsV4' Swift 4