"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

crash Kernel Page Error

注意位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层,只使用03。这里的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

如果CPL3的时候发生系统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

扩展psfiles

可以看到

  • 检查文件

内核源代码获取

参考

Last updated

Was this helpful?