前提知识:
Linux内核、Linux 进程和文件数据结构、vmcore解析、汇编语言
问题背景:
这个问题出自项目的一个安全模块,主要功能是确定某进程是否有权限访问其正在访问的文件。
实现功能时,需要在内核里通过扫描该进程打开的文件表,获取文件的路径,和安全模块里配置的可访问文件的进程白名单进行匹配;
模块会一直到搜索到进程pid为1的进程,也就是init进程。在访问中间某个父进程的文件表时,出现struct task_struct的files指针为空的情况,
导致系统异常复位。
下面就是这次异常的分析和定位过程,希望对大家有所帮助,有什么想法我们可以交流讨论。
接到现场保障时,没想到又是这个模块导致的,因为这个模块刚升级版本,首先是确认系统有无crash vmcore文件生成,还好这次有
vmcore文件,先登录上去看异常堆栈吧。
确实是安全内核模块出了异常,为了保密,我省去了很多信息。
在dmesg.txt文件里,还有一句话:
<1>[259267.001561] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
从堆栈信息可以产出,异常进程comm名称是gzip,pid为10877,task指针为ffff88207f7f2380,异常原因是访问了NULL指针。
通过nm和addr2line命令,我们定位具体出异常的代码行:
include/linux/fdtable.h: 87
紧接着查看files_fdtable代码实现,是对files->fdt的访问:
#define files_fdtable(files)
(rcu_dereference_check_fdtable((files), (files)->fdt))
分析到这里,初步判断是访问files执行了异常。我们结合vmcore信息进一步确认。
vmcore文件分析
查找异常进程的files成员变量值是正常的,如下所示:
## crash> struct task_struct.files ffff88207f7f2380
## files = 0xffff881f97cff380
异常进程的进程名称:
## crash> struct task_struct.comm ffff88207f7f2380
## comm = "gzip