内核vmcore文件分析方法

linux内核在运行过程中,总会由于硬件异常,驱动异常或者用户态程序等等原因导致coredump,从而转储vmcore文件。而coredump发生后,我们如何去分析coredump愿原因,成为了维护内核工作的重点,那么我们怎么去分析coredump呢,接下来就让我们一起来看看。

一、开启coredump转储

现在linux系统中,默认都开启了内核coredump转储功能。我们可以通过ulimit -c命令进行确认。

如果ulimit -c显示为0,证明被关闭(限制core文件的大小为0,意为不转储),我们可以设置为

ulimit -c unlimited

二、coredump文件的常用分析工具和方法

首先,我们要知道分析内核需要什么,其实我们需要3个东西:

1)crash工具

2)coredump转储的文件,即vmcore文件

3)发生奔溃的内核映像文件(vmlinux文件,虽然boot目录下也有vmliunz-xxx文件,但是boot下的这个文件被压缩过,不包含我们调试需要的信息,所以无法用它来进行调试工作),这里包含了调试内核所需要的调试信息(和我们调试程序时添加-g参数编出来的文件相似)

1、安装分析coredump所需的包

首先,我们系统一般不会预装crash工具和内核debug包,所以我们分析内核的vmcore文件,需要安装以下包:

  • crash
  • kernel-debuginfo
  • kernel-debuginfo-common

可以联网yum源的环境,直接yum install crash kernel-debuginfo kernel-debuginfo-common即可;yum源不可用的环境,可以通过在网上找到对应的rpm包,直接使用wget下载后,rpm -ivh *rpm安装。

注意:这里的kernel-debuginfo包的版本必须与当前发生coredump的内核完全版本一致,如果不一致会因为符号不一致,导致后续crash命令无法正常解析vmcore文件。

安装完成后,在系统的/lib/debug/lib/modules/xxx(内核版本)/下有问们需要的vmlinux文件。

2、crash命令的用法说明

①bt命令

backtrace,打印内核栈信息。

bt pid 打印指定进程栈信息

最重要的信息:[exception RIP: sysrq_handle_crash+22],指出发生异常的指令信息

RIP: ffffffffa54627a6,可以得知,发生crash的函数是sysrq_handle_crash中,偏移22字节处的指令。

这里,对应x86-64汇编,应用层下来的系统调用对应的6个参数存放的寄存器依次对应:rdi、rsi、rdx、rcx、r8、r9。对于多于6个参数的,仍存储在栈上。

②dis命令

使用bt命令我们会看到[exception RIP: sysrq_handle_crash+22]信息,那这条指令在做什么呢。就需要使用dis命令(dis -l (function+offset) 10 反汇编出指令所在代码开始,10行代码)

③sym命令

sym 转换指定符号为其虚拟地址,显示系统中符号信息

如上面bt打印的RIP: ffffffffc07c5024,使用sym转换查看系统符号信息
sym addr 通过虚拟地址,显示symbol和源码位置

然后我们可以对照着代码,来辅助我们进行问题分析。

④ps命令

ps 打印内核崩溃时的进程信息

⑤log命令

打印vmcore所在的系统内核日志信息,可以分析出当时,内核启动的各项配置,内核最后崩溃时异常日志信息。

⑥p命令

p命令可以用来打印出表达式或者变量的值

⑦kmem命令

查看当时系统内存使用信息

⑧task

task 查看当前进程或指定进程task_struct和thread_info的信息(系统进程导致的奔溃,我们往往需要查看进程的信息)

⑨其他命令

可以通过help直接查看,如下:

三、举例分析

1、场景的coredump场景

造成程序coredump的原因有很多,比较常见的有:

1)硬件异常

硬件异常其实也很常见,他可能是一个由ipmitool监控到的一个硬件异常,然后给内核发送诸如Serror的异常中断;也可能是内存ECC异常(比如不可纠正的内存异常,ECC异常发生原理可以参考内存ECC问题的分析和实践-CSDN博客);亦可能是pci总线异常(硬件引脚接触不良,无法上电下电之类)7等等。

这类异常我们没法通过软件或者内核层面去解决,只能去排查硬件问题。而我们使用crash分析vmcore文件主要是为了解决软件的异常。必须如下面的5个场景场景。

2)内存访问越界

a) 由于使用错误的下标,导致数组访问越界。
b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符。
c) 使用strcpy, strcat, sprintf, strcmp,strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。

3)多线程程序使用了线程不安全的函数

应该使用下面这些可重入的函数,它们很容易被用错:
asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n)ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c)getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c)fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c)getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3)getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n)nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3)getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c)getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c)getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)

4)多线程读写的数据未加锁保护

对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成coredump

5)非法指针

a) 使用空指针
b) 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它时就很容易因为bus error而core dump。

6)堆栈溢出

不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。

2、实际coredump场景模拟和分析

1)先写一个ha-check脚本,脚本里执行以下命令模拟一个空指针导致的内核panic。

echo 1 >/proc/sys/kernel/sysrq

echo c >/proc/sys/kernel/sysrq

2)crash分析vmcore

其实crash一开始就会给我们列出coredump的原因,我们模拟的这次coredump导致内核奔溃的原因是PANIC: "BUG: unable to handle kernel NULL pointer dereference at           (null)"对应的进程是PID: 13165,进程指令名称是COMMAND: "ha-check"。

包括bt显示的调用栈也清晰的写明了奔溃的来源,如下:

从上我们还可以看出明显由一个sysrq_trigger的写入动作。(正好我们的ha-check也是执行了一个echo c >/proc/sys/kernel/sysrq模拟内核奔溃的示例)。而上面奔溃的地方是[exception RIP: sysrq_handle_crash+22]这里,对应下方代码:

我们都指导,指针初始化时赋值位为NULL时,编译虽然没问题,但是会运行错误,指针所指向地址必须为合法有效的内存地址。所以模拟的奔溃错误是”unable to handle kernel NULL pointer dereference at           (null)”。

四、参考资料

1.coredump详解_coredump文件分析_贺二公子的博客-CSDN博客

2.crash分析linux内核崩溃转储文件vmcore_linux crash分析-CSDN博客

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会写代码的小可爱&&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值