【微信群问题讨论】如何检查内核stack是否被破坏?
本文是原「蜗窝讨论区」的历史存档(2017-07-17),来自版块「Linux kernel技术问答」,共 2 帖。讨论区已停止服务,此处仅供查阅。
问题的提出:早上好,请问大侠们, kernel stack bottom是不是固定的. 最近我们发现有些case下面, stack爆了. 系统报告未定义指令的异常。我们怀疑是内核栈太大,覆盖了内核栈顶部的thread_info而导致的这个issue。我们的思路是:现在我得到了出问题的stack top pointer. 所以如果知道bottom的话, 就能算出是不是stack overflow。
整体思路: 直面问题,不能通过加大内核栈来修复这个issue。主要是因为改stack牵扯太多,内存消耗也增多。 如果正面攻击该issue,需要一些调试的手段,包括: 1、静态检查的方法。配置项是CONFIG_FRAME_WARN,这个选项可以让gcc在编译的时候做stack frame的检查。例如配置CONFIG_FRAME_WARN=1024,那么在编译内核的时候,如果stack frame的大小大于1024,那么就会报警。通过这个方法可以知道哪个模块使用的stack memory比较大,他们就是潜在的引起statck overflow的怀疑对象。
2、系统运行时,动态跟踪栈的使用情况。配置项是CONFIG_STACK_TRACER。这个配置项用来跟踪最大的栈的使用场景,当配置了该选项之后,内核会自动跟踪内核栈的情况并将信息输出到/sys/kernel/debug/tracing/stack_trace中。
3、运行时检查stack overflow。配置项是CONFIG_CC_STACKPROTECTOR。这种方法是在函数的开始和结尾处增添代码,发现有stack overflow,则直接panic。
最后的解决方法: 1、压测机器会出现undefined instruction, 但是PC都没有跑飞, 发生kernel oops 2、日志分析发现:从log里面看栈帧已经爆掉了, 栈帧限制:stack limit = 0xecdf2238 目前的栈顶: sp : ecdf3fb0 3、加入CONFIG_FRAME_WARN,在编译kernel的时候会打印出warning: the frame size of 3128 bytes is larger than 1080 bytes 4、从warning打印里面可以看到函数的行数, 追查到此函数使用了一个很大的结构体 typedef struct { U32 u32Output[512]; U16 u16Input[512] }NG_St;
void NG_Func({ NG_St ng_st; xxxx return; } 5、把大数组转成指针, 用heap里面的memory存资料,问题解决。
从log里看 no frame pointer, 而且Stack附近找不到函数指针. 说明stack里面包含的数据有问题, 怀疑是stack overflow.
