宿主机配置:Intel 8378 cpu + ctyunos 64内核, cpu 微码版本:0d000311
卡死时的vmcore-dmesg.txt 中call trace如下:
图-1
crash调试bt如下:
图-2
图-3
异常地址0xfffef7efbfee2dba,但查看该地址也不在正常的内核地址映射范围之内:
图-4
内核异常时的错误码为0x0010,对应指令预取造成
图-5
反汇编EIP对应地址为
图-6
从上边堆栈IP的值是0xffffffff8c6e1e40,也就是x86_sys_ioctl的入口地址。
也就是说异常发生在x86_sys_ioctl的入口地址。
那我们看看是如何跳转到x86_sys_ioctl,跳转过程中有无异常。
__x64_sys_ioctl的更上一层的栈信息(_MODULE_START_syshook_linux at ffffffffc08e5b93 [syshook_linux])如下:
图-7
上一个堆栈发生问题的地方是一条跳转指令,反汇编跳转地址0xffffffff8d003000。
图-8
此处进入__x64_sys_ioctl路径如下:
这个函数开始就执行了一条跳转指令,跳转到rax,根据上面异常堆栈的情况,rax的值为
0xffffffff8c6e1e40,也就是跳转到__x64_sys_ioctl时发生了异常。
call 0xffffffff8d003000àjmpq *raxà__x64_sys_ioctl
结论:
从上面的分析日志和分析可以看出,内存中RAX和IP寄存器的值是正确的,不存在内存中IP地址非法的问题。但在跳转过程中,cpu IP寄存器得到了一个非法地址,导致cpu指令预取失败,内核crash。后续intel加入分析,发现有一个微码bug和此问题类似,主机更新微码后未再出现。
此类问题单纯从软件分析会发现非常奇怪,代码突然跑飞,此时可以考虑微码问题,可升级到最新微码再验证。