[fw]Understanding a Kernel Oops!
An “Oops” is what the kernel throws at us when it finds something faulty, or an exception, in the kernel code. It’s somewhat like the segfaults of user-space. An Oops dumps its message on the console; it contains the processor status and the CPU registers of when the fault occurred. The offending process that triggered this Oops gets killed without releasing locks or cleaning up structures. The system may not even resume its normal operations sometimes; this is called an unstable state. Once an Oops has occurred, the system cannot be trusted any further.
Let’s try to generate an Oops message with sample code, and try to understand the dump.
Setting up the machine to capture an Oops
The running kernel should be compiled with CONFIG_DEBUG_INFO, and syslogd should be running. To generate and understand an Oops message, Let’s write a sample kernel module,oops.c:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> static void create_oops() { *(int *)0 = 0; } static int __init my_oops_init(void) { printk("oops from the module\n"); create_oops(); return (0); } static void __exit my_oops_exit(void) { printk("Goodbye world\n"); } module_init(my_oops_init); module_exit(my_oops_exit); |
The associated Makefile for this module is as follows:
obj-m := oops.o KDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd) SYM=$(PWD) all: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules |
Once executed, the module generates the following Oops:
BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<ffffffffa03e1012>] my_oops_init+0x12/0x21 [oops] PGD 7a719067 PUD 7b2b3067 PMD 0 Oops: 0002 [#1] SMP last sysfs file: /sys/devices/virtual/misc/kvm/uevent CPU 1 Pid: 2248, comm: insmod Tainted: P 2.6.33.3-85.fc13.x86_64 RIP: 0010:[<ffffffffa03e1012>] [<ffffffffa03e1012>] my_oops_init+0x12/0x21 [oops] RSP: 0018:ffff88007ad4bf08 EFLAGS: 00010292 RAX: 0000000000000018 RBX: ffffffffa03e1000 RCX: 00000000000013b7 RDX: 0000000000000000 RSI: 0000000000000046 RDI: 0000000000000246 RBP: ffff88007ad4bf08 R08: ffff88007af1cba0 R09: 0000000000000004 R10: 0000000000000000 R11: ffff88007ad4bd68 R12: 0000000000000000 R13: 00000000016b0030 R14: 0000000000019db9 R15: 00000000016b0010 FS: 00007fb79dadf700(0000) GS:ffff880001e80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000000 CR3: 000000007a0f1000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process insmod (pid: 2248, threadinfo ffff88007ad4a000, task ffff88007a222ea0) Stack: ffff88007ad4bf38 ffffffff8100205f ffffffffa03de060 ffffffffa03de060 0000000000000000 00000000016b0030 ffff88007ad4bf78 ffffffff8107aac9 ffff88007ad4bf78 00007fff69f3e814 0000000000019db9 0000000000020000 Call Trace: [<ffffffff8100205f>] do_one_initcall+0x59/0x154 [<ffffffff8107aac9>] sys_init_module+0xd1/0x230 [<ffffffff81009b02>] system_call_fastpath+0x16/0x1b Code: <c7> 04 25 00 00 00 00 00 00 00 00 31 c0 c9 c3 00 00 00 00 00 00 00 RIP [<ffffffffa03e1012>] my_oops_init+0x12/0x21 [oops] RSP <ffff88007ad4bf08> CR2: 0000000000000000 |
Understanding the Oops dump
Let’s have a closer look at the above dump, to understand some of the important bits of information.
BUG: unable to handle kernel NULL pointer dereference at (null) |
The first line indicates a pointer with a NULL value.
IP: [<ffffffffa03e1012>] my_oops_init+0x12/0x21 [oops] |
IP is the instruction pointer.
Oops: 0002 [#1] SMP |
This is the error code value in hex. Each bit has a significance of its own:
bit 0== 0 means no page found, 1 means a protection faultbit 1== 0 means read, 1 means writebit 2== 0 means kernel, 1 means user-mode[#1]— this value is the number of times the Oops occurred. Multiple Oops can be triggered as a cascading effect of the first one.
CPU 1 |
This denotes on which CPU the error occurred.
Pid: 2248, comm: insmod Tainted: P 2.6.33.3-85.fc13.x86_64 |
The Tainted flag points to P here. Each flag has its own meaning. A few other flags, and their meanings, picked up from kernel/panic.c:
P— Proprietary module has been loaded.F— Module has been forcibly loaded.S— SMP with a CPU not designed for SMP.R— User forced a module unload.M— System experienced a machine check exception.B— System has hit bad_page.U— Userspace-defined naughtiness.A— ACPI table overridden.W— Taint on warning.
RIP: 0010:[<ffffffffa03e1012>] [<ffffffffa03e1012>] my_oops_init+0x12/0x21 [oops] |
RIP is the CPU register containing the address of the instruction that is getting executed. 0010comes from the code segment register. my_oops_init+0x12/0x21 is the <symbol> + the offset/length.
RSP: 0018:ffff88007ad4bf08 EFLAGS: 00010292 RAX: 0000000000000018 RBX: ffffffffa03e1000 RCX: 00000000000013b7 RDX: 0000000000000000 RSI: 0000000000000046 RDI: 0000000000000246 RBP: ffff88007ad4bf08 R08: ffff88007af1cba0 R09: 0000000000000004 R10: 0000000000000000 R11: ffff88007ad4bd68 R12: 0000000000000000 R13: 00000000016b0030 R14: 0000000000019db9 R15: 00000000016b0010 |
This is a dump of the contents of some of the CPU registers.
Stack: ffff88007ad4bf38 ffffffff8100205f ffffffffa03de060 ffffffffa03de060 0000000000000000 00000000016b0030 ffff88007ad4bf78 ffffffff8107aac9 ffff88007ad4bf78 00007fff69f3e814 0000000000019db9 0000000000020000 |
The above is the stack trace.
Call Trace: [<ffffffff8100205f>] do_one_initcall+0x59/0x154 [<ffffffff8107aac9>] sys_init_module+0xd1/0x230 [<ffffffff81009b02>] system_call_fastpath+0x16/0x1b |
The above is the call trace — the list of functions being called just before the Oops occurred.
Code: <c7> 04 25 00 00 00 00 00 00 00 00 31 c0 c9 c3 00 00 00 00 00 00 00 |
The Code is a hex-dump of the section of machine code that was being run at the time the Oops occurred.
Debugging an Oops dump
The first step is to load the offending module into the GDB debugger, as follows:
[root@DELL-RnD-India oops]# gdb oops.ko GNU gdb (GDB) Fedora (7.1-18.fc13) Reading symbols from /code/oops/oops.ko...done. (gdb) add-symbol-file oops.o 0xffffffffa03e1000 add symbol table from file "oops.o" at .text_addr = 0xffffffffa03e1000 |
Next, add the symbol file to the debugger. The add-symbol-file command’s first argument isoops.o and the second argument is the address of the text section of the module. You can obtain this address from /sys/module/oops/sections/.init.text (where oops is the module name):
(gdb) add-symbol-file oops.o 0xffffffffa03e1000add symbol table from file "oops.o" at .text_addr = 0xffffffffa03e1000 (y or n) y Reading symbols from /code/oops/oops.o...done. |
From the RIP instruction line, we can get the name of the offending function, and disassemble it.
(gdb) disassemble my_oops_init Dump of assembler code for function my_oops_init: 0x0000000000000038 <+0>: push %rbp 0x0000000000000039 <+1>: mov $0x0,%rdi 0x0000000000000040 <+8>: xor %eax,%eax 0x0000000000000042 <+10>: mov %rsp,%rbp 0x0000000000000045 <+13>: callq 0x4a <my_oops_init+18> 0x000000000000004a <+18>: movl $0x0,0x0 0x0000000000000055 <+29>: xor %eax,%eax 0x0000000000000057 <+31>: leaveq 0x0000000000000058 <+32>: retqEnd of assembler dump. |
Now, to pin point the actual line of offending code, we add the starting address and the offset. The offset is available in the same RIP instruction line. In our case, we are adding0x0000000000000038 + 0x012 = 0x000000000000004a. This points to the movl instruction.
(gdb) list *0x000000000000004a 0x4a is in my_oops_init (/code/oops/oops.c:6). 1 #include <linux/kernel.h> 2 #include <linux/module.h> 3 #include <linux/init.h> 4 5 static void create_oops() { 6 *(int *)0 = 0; 7 } |
This gives the code of the offending function.
References
The kerneloops.org website can be used to pick up a lot of Oops messages to debug. The Linux kernel documentation directory has information about Oops — kernel/Documentation/oops-tracing.txt. This, and numerous other online resources, were used while creating this article.
Related Posts:
[fw]Understanding a Kernel Oops!的更多相关文章
- Understanding a Kernel Oops!
Understanding a kernel panic and doing the forensics to trace the bug is considered a hacker's job. ...
- Linux Kernel Oops异常分析
1.PowerPC小系统内核异常分析 1.1 异常打印 Unable to handle kernel paging request for data at address 0x36fef31eFa ...
- 如何解读Linux Kernel OOPS信息
OOPS信息解读 root@firefly:~/mnt/module# insmod oops_module.ko [ 867.140514] Unable to handle kernel NULL ...
- Understanding Linux Kernel version 3 读书笔记
P30, preemptive kernel .kernel threading 和Multithreaded application support没太好理解,我想如果设计个多线程的程序来运行运行 ...
- Linux Kernel PANIC(三)--Soft Panic/Oops调试及实例分析【转】
转自:https://blog.csdn.net/gatieme/article/details/73715860 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...
- Kernel boot options
There are three ways to pass options to the kernel and thus control its behavior: When building the ...
- 学习kernel编程的建议
我把我学习kernel编程的过程介绍给大家,希望大家有个参考. 学习kernel编程需要阅读大量的kernel方面的书籍,在此我列举一下我读过的kernel书籍(按时间先后顺序),并给一些建议. 1. ...
- 绕过kernel模块版本校验检测
kernel module version check bypass . 举例说明 . 内核是怎么实现的 . 怎样去突破 . 总结 . 举例说明 Linux内核版本很多,升级很快,2个小内核版本中内核 ...
- 依据linux Oops信息准确定位错误代码所在行
在linux下调tvp5150am1的过程中,遇到了一kernel oops,内容如下: [ 66.714603] Unable to handle kernel paging request a ...
随机推荐
- 88-基于FMC接口的2路CameraLink Base输入子卡模块
基于FMC接口的2路CameraLink Base输入子卡模块 1.板卡概述 FMC连接器是一种高速多pin的互连器件,广泛应用于板卡对接的设备中,特别是在xilinx公司的所有开发板中都使用.该Ca ...
- debian系列systemd 配置nodejs服务
1 新建service配置文件 vi /etc/systemd/system/node.service [Unit] Description=My super nodejs app [Service ...
- csv导入数据
1.关闭Neo4j服务器进程 2.删除graph.db数据库文件 /data/databases/ rm -rf graph.db 3.重新启动Neo4j服务器 4.数据导入import 5.wi ...
- mysql 乐观锁、悲观锁、共享锁,排它锁
mysql锁机制分为表级锁和行级锁,本文就和大家分享一下我对mysql中行级锁中的共享锁与排他锁进行分享交流. 共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能 ...
- 前端每日实战:21# 视频演示如何用纯 CSS 创作文本滑动特效的 UI 界面
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/QrxxaW 可交互视频教程 此视频 ...
- struts2+ajax 前后端传值
摘要: 主要实现步骤如下: 1.JSP页面使用脚本代码执行ajax请求 2.Action中查询出需要返回的数据,并转换为json类型模式数据 3.配置struts.xml文件 4.页面脚本接受并处理数 ...
- @ResponseBody和@RestController
Spring 关于ResponseBody注解的作用 responseBody一般是作用在方法上的,加上该注解表示该方法的返回结果直接写到Http response Body中,常用在ajax异步请求 ...
- 1,Spring MVC 学习总结(一)
一,什么是MVC MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示 ...
- Android逆向之旅---解析编译之后的AndroidManifest文件格式
一.前言 今天又是周六了,闲来无事,只能写文章了呀,今天我们继续来看逆向的相关知识,我们今天来介绍一下Android中的AndroidManifest文件格式的内容,有的同学可能好奇了,Android ...
- ARP(Address Resolution Protocol)地址解析协议初识
ARP址解析协议是根据IP地址获取物理地址的一个TCP/IP协议.它工作在OSI七层模型的中第二层——数据链路层. 使用ARP地址解析协议,可根据网络层IP数据包包头中的IP地址信息解析出目标硬件地址 ...