一、问题描述
进程收到SIGABRT信号异常退出,异常调用栈显示__stack_chk_fail
二、原因分析和定位思路
原因分析: __stack_chk_fail说明发生了缓冲区溢出,canary被破坏。这说明代码设置GCC编译选项fstack-protector,开启了栈保护机制canary
定位思路:
- 先通过反汇编找到
canary在栈上的存放地址。 - 用GDB对
canary的存放地址打数据断点,定位出导致栈破坏的指令,再结合C代码具体分析。
三、定位过程
以下给出一个简化案例:一个可执行程序test, 依赖两个.so:libcomp1.so, libcomp2.so。执行test程序后会异常退出,调用栈显示__stack_chk_fail
├── CMakeLists.txt —— 可执行程序 test, 依赖libcomp1.so, libcomp2.so
├── comp1
│ ├── CMakeLists.txt —— libcomp1.so
│ ├── comp1.c
│ ├── lua.h
├── comp2
│ ├── CMakeLists.txt -- libcomp2.so
│ ├── comp2.c
│ ├── lua.h
├── main.c
C代码如下:
// main.c
extern void func1(); // defined in libcomp1.so
void main() {
func1();
}
// comp1/comp1.c
#include "lua.h"
extern func2(struct lua_Debug *a, char *b, int c); // defined in libcomp2.so
void func1() {
struct lua_Debug a = {0};
char *b = 0x12345678;
int c = 0xFFFFFFFF;
func2(&a, b, c);
return;
}
// comp2/comp2.c
#include "lua.h"
void func2(struct lua_Debug *a, char *b, int c) {
a->i_ci = 1;
return;
}
用GDB调试test程序,出现如下的异常调用栈
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff7e1c535 in __GI_abort () at abort.c:79
#2

本文详细解析了进程收到SIGABRT信号时的异常退出,聚焦于__stack_chk_fail异常。通过分析C代码和使用GDB定位,展示了如何通过反汇编追踪canary,揭示了不同.so依赖的lua.h头文件不一致导致的栈溢出问题。同时介绍了如何利用GCC的fstack-protector选项加强栈保护。

743

被折叠的 条评论
为什么被折叠?



