"Kernel panic - not syncing: stack-protector: Kernel stack is corrupted"
虚拟机crash的一个案例,类似参考 vmcore分析案例:"kernel BUG at fs/buffer.c:1270" 使用crash分析
首先获取core对应虚拟机的内核版本
sudo strings -n 50 2017-0411-0913.48-i-23ljwikin.301864.118695.897.core | head -n 30000 | grep -m 1 '^Linux version'假设内核版本是 2.6.32-573.22.1.el6.x86_64 使用以下命令获取debuginfo包以获得对应的vmlinux:
export kernel_version=2.6.32-573.22.1.el6.x86_64
wget http://debuginfo.centos.org/6/x86_64/kernel-debuginfo-${kernel_version}.rpm
rpm2cpio kernel-debuginfo-${kernel_version}.rpm | cpio -idv ./usr/lib/debug/lib/modules/${kernel_version}/vmlinux
crash ./usr/lib/debug/lib/modules/${kernel_version}/vmlinux 2017-0411-0913.48-i-23ljwikin.301864.118695.897.core可以看到导致kernel panic的原因是stack-protector: Kernel stack is corrupted
KERNEL: vmlinux
DUMPFILE: 2017-0409-0418.11-AY1307061945475866c5.155086.33872.487.core
CPUS: 2 [OFFLINE: 1]
DATE: Sun Apr 9 04:18:10 2017
UPTIME: 17:13:25
LOAD AVERAGE: 2.00, 2.10, 2.48
TASKS: 155
NODENAME: kamiconf4
RELEASE: 2.6.32-279.el6.x86_64
VERSION: #1 SMP Fri Jun 22 12:19:21 UTC 2012
MACHINE: x86_64 (2194 Mhz)
MEMORY: 2 GB
PANIC: "Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffffa016087c"
PID: 10522
COMMAND: "AliHids"
TASK: ffff88007c002080 [THREAD_INFO: ffff88000c8f8000]
CPU: 0
STATE: TASK_RUNNING (PANIC)使用
sys命令也可以显示上述信息
检查历史记录,每次crash的时候,出现的panic都是位于 stack-protector: Kernel stack is corrupted in: ffffffffa016087c ,内存地址都是ffffffffa016087c
使用dmesg指令查看,可以看到
Not tainted 2.6.32-279.el6.x86_64表明内核没有强制加载的内核模块(这里采用的是标准的CentOS 6.3系统,内核无污染)
参考 Kernel Page Error 如果在Oops部分看到decimal code of the Kernel Page Error(4位数值,例如Oops: 0002)
注意位0到3是从右到左
0002 (dec) --> 0010 (binary) --> Not instruction fetch|Kernel mode|Write|Invalid access
反向跟踪
我们需要分析进程的执行历史,这里需要使用backtrace,也就是bt指令
这里有一个BUG: 上述采用CentOS 5.11操作系统下编译crash最新版本,来分析
bt的时候,会出现bt: WARNING: possibly bogus exception frame,参考 Bug 802234 - WARNING: possibly bogus exception frame,原来这个BUG在CentOS 7上已经得到修复。转换到CentOS 7平台,同样使用
crash ./usr/lib/debug/lib/modules/2.6.32-279.el6.x86_64/vmlinux 2017-0326-0343.02-AY1307061945475866c5.155086.33872.482.core,就不再出现告警,而输出的正确内容如下
所以,要正确分析crash core dump,应该在最新的CentOS 7平台上使用crash来完成。否则,会明显看到寄存器内容读取错误,出现诡异的CS: 202020202020200a。正确的CS内容在CentOS 7平台可以解析出CS: 0033
Call trace
这里以#开头的表示call trace,也就是先前crash时执行内核功能的列表,这里可以看出系统宕机前的迹象。
指令指针
RIP表示指令指针(instruction point, IP),也就是指向内存地址,表示在内存中程序进程地址。
注意:在32位系统中,指令指针称为
EIP如果有类似
[exception RIP: default_idle+61]则表示RIP指向的内核功能是default_idle,+61是偏移量(十进制),也就是异常发生的位置。
代码段(Code Segment, CS)寄存器
在Call Trace之后的内容是寄存器内容输出,大多数没有太大用途。不过,有一个CS(Code Segment)寄存器需要注意
Privilege levels(特权级别)概念
privilege level是CPU的保护资源的概念。不同执行线程可以有不同的特权级别,以允许访问系统资源,类似内存区域,I/O端口,等等。有4个特权级别,从0到3。0层是最高权限,也就是内核态;3层则权限最低,也就是用户态。
大多数现代操作系统,包括linux,不使用中间2层,只使用0和3。这里的level也称为ring(环)。
当前特权层(Current Privilege Level, CPL)
Code Segment(CS) register是一个指向程序指令设置的段的指针。该寄存器2个最小的重要位指示了CPU的当前特权层(Current Privilege Level, CPL)。这两位代表的数值是0到3。
描述符特权级别(Descriptor Privilege Level, DPL)和 请求特权界别(Requested Privilege Level, RPL)
描述符特权级别(Descriptor Privilege Level, DPL)是被能够访问资源和被定义级别更高级别的权限。这个值在段描述符(Segement Descriptor)中定义。请求特权级别(RPL)是在段选择器(Segment Selector)中定义,至少2位。精确地来说,CPL是不允许超过最大值(RPL, DPL),如果超过,就会导致一般保护错误(General Protection Fault, GPF)。
注意 CPL
如果CPL是3的时候发生系统crash,则表示是由于硬件故障导致的,因为系统不可能由于用户态的错误导致crash。
相反,则可能是由于存在bug的系统调用导致的问题。
更多信息,请参考O'Reilly的Understanding Linux Kernel 第二章 "内存地址" 中有关 Segment Selectors, Segment Descriptors, Table Index, Global and Local Descriptor Tables , Current Privilege Level (CPL)等概念。
在这里的案例 CS: 0033,表示
内核crash时的功能调用
前述案例中crash时执行内核功能的列表
可以看到功能调用顺序
backtrace所有任务
默认情况下,crash智慧显示活跃任务的backtrace,如果要查看所有任务的backtrace,需要使用foreach
dump系统消息缓存
log命令可以显示系统message buffer。在这个内核log buffer(log_buf)有可能包含有用的crash信息。不过,如果发生了间歇性的硬件故障或者纯软件bug,这个log命令可能没有什么帮助。
尝试了发现实际和dmesg没有差别
显示进程状态信息
ps 命令可以显示进程状态信息:
这里>表示active task
注意:一定要使用正确的操作系统和crash,我遇到在CentOS 5上使用crash错误指向了active task
可以看到和bt显示的一样 PID: 10522 TASK: ffff88007c002080 CPU: 0 COMMAND: "AliHids",这里可以从ffff88007c002080任务地址看到AliHids
分析
完整显示backtrace
查看源代码
#4 [ffff88007be43e70] __stack_chk_fail at ffffffff8106b85b
dis -l (function+offset)-- disassemble
这里可以看到源代码以及所在行
类似倒推,一共有4个函数需要检查
#3 [ffff88007be43df0] panic at ffffffff814fd145
[ffff88007be43de0] atomic_notifier_call_chain at ffffffff8150338a
[ffff88007be43da0] notifier_call_chain at ffffffff81503325
#0 [ffff88007be43d80] xen_panic_event at ffffffff810033c2
扩展ps和files
ps和files可以看到
检查文件
内核源代码获取
参考
Last updated
Was this helpful?