Linux内核模块调试一

2024-09-05 20:08
文章标签 linux 调试 内核模块

本文主要是介绍Linux内核模块调试一,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

      接下来写个专栏专门讲我们写的linux内核模块出现异常时如何定位和调试。我们先构造一个最简单的内核空指针玩玩。

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>struct __ops_dev{char dev_name[64];}ops_dev_t;int __init oops_init(void)
{int * p =NULL;pr_warn("will init\n");*p=1;return 0;
}void __exit oops_uninit(void)
{pr_warn("will exit\n");return ;
}module_init(oops_init);
module_exit(oops_uninit);
MODULE_LICENSE("GPL");           

 来看看我们的makefile写法

obj-m:=oops.o
EXTRA_CFLAGS += -g
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:$(MAKE) -C $(KERNELDIR)  M=$(PWD) modules
clean:rm -rf *.o *.mod.c *.mod.o *.ko
endif

插入模块后dmesg我们可以看到,发生了Oops,其实需要一些背景信息就是寄存器,这里以x86为实验,所以看到有RIP,RIP标识的是当前指令执行地址,我们可以看到是在init_module符号的偏移0x17处。意味着在0x17偏移处出现了错误。

[  237.823288] oops: loading out-of-tree module taints kernel.
[  237.823320] oops: module verification failed: signature and/or required key missing - tainting kernel
[  237.823664] will init
[  237.823668] BUG: kernel NULL pointer dereference, address: 0000000000000000
[  237.823670] #PF: supervisor write access in kernel mode
[  237.823671] #PF: error_code(0x0002) - not-present page
[  237.823672] PGD 0 P4D 0 
[  237.823674] Oops: 0002 [#1] SMP NOPTI
[  237.823676] CPU: 0 PID: 2451 Comm: insmod Tainted: G           OE     5.11.0-22-generic #23-Ubuntu
[  237.823678] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 02/27/2020
[  237.823679] RIP: 0010:init_module+0x17/0x1000 [oops]
[  237.823682] Code: Unable to access opcode bytes at RIP 0xffffffffc07d1fed.
[  237.823683] RSP: 0018:ffffb59843c43d60 EFLAGS: 00010246
[  237.823685] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff981539e18ac8
[  237.823686] RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff981539e18ac0
[  237.823687] RBP: ffffb59843c43d60 R08: 0000000000000000 R09: ffffb59843c43b58
[  237.823687] R10: ffffb59843c43b50 R11: ffff98153fec68a8 R12: ffffffffc07d2000
[  237.823688] R13: ffff981429558510 R14: 0000000000000000 R15: ffffffffc0848000
[  237.823689] FS:  00007f11f3cc1580(0000) GS:ffff981539e00000(0000) knlGS:0000000000000000
[  237.823691] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  237.823692] CR2: ffffffffc07d1fed CR3: 000000001feee002 CR4: 00000000003706f0
[  237.823709] Call Trace:
[  237.823712]  do_one_initcall+0x48/0x1d0
[  237.823715]  ? kmem_cache_alloc_trace+0xf6/0x200
[  237.823718]  ? do_init_module+0x28/0x290
[  237.823720]  do_init_module+0x62/0x290
[  237.823722]  load_module+0x6fd/0x780
[  237.823723]  __do_sys_finit_module+0xc2/0x120
[  237.823725]  __x64_sys_finit_module+0x1a/0x20
[  237.823726]  do_syscall_64+0x38/0x90
[  237.823728]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  237.823730] RIP: 0033:0x7f11f3dfcf6d
[  237.823732] Code: 28 0d 00 0f 05 eb a9 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d cb de 0c 00 f7 d8 64 89 01 48
[  237.823734] RSP: 002b:00007fff7002cdb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[  237.823736] RAX: ffffffffffffffda RBX: 000055f0f974d790 RCX: 00007f11f3dfcf6d
[  237.823736] RDX: 0000000000000000 RSI: 000055f0f7b04260 RDI: 0000000000000003
[  237.823737] RBP: 0000000000000000 R08: 0000000000000000 R09: 00007f11f3ecf520
[  237.823738] R10: 0000000000000003 R11: 0000000000000246 R12: 000055f0f7b04260
[  237.823739] R13: 0000000000000000 R14: 000055f0f974d760 R15: 0000000000000000
[  237.823740] Modules linked in: oops(OE+) nls_utf8 isofs rfcomm xt_conntrack nft_chain_nat xt_MASQUERADE nf_nat nf_conntrack_netlink nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 xfrm_user xfrm_algo nft_counter xt_addrtype nft_compat nf_tables libcrc32c nfnetlink br_netfilter bridge stp llc overlay bnep vsock_loopback vmw_vsock_virtio_transport_common vmw_vsock_vmci_transport vsock nls_iso8859_1 intel_rapl_msr intel_rapl_common snd_ens1371 snd_ac97_codec crct10dif_pclmul gameport ghash_clmulni_intel ac97_bus snd_pcm snd_seq_midi snd_seq_midi_event aesni_intel crypto_simd cryptd glue_helper rapl vmw_balloon snd_rawmidi snd_seq joydev input_leds snd_seq_device serio_raw snd_timer snd soundcore vmw_vmci mac_hid btusb btrtl btbcm btintel bluetooth ecdh_generic ecc sch_fq_codel vmwgfx ttm drm_kms_helper cec rc_core fb_sys_fops syscopyarea sysfillrect sysimgblt msr parport_pc ppdev drm lp parport ip_tables x_tables autofs4 hid_generic usbhid hid crc32_pclmul mptspi mptscsih psmouse ahci e1000
[  237.823777]  libahci mptbase scsi_transport_spi i2c_piix4 pata_acpi
[  237.823781] CR2: 0000000000000000
[  237.823782] ---[ end trace 4f3baa0cf2fdf2af ]---
[  237.823783] RIP: 0010:init_module+0x17/0x1000 [oops]
[  237.823786] Code: Unable to access opcode bytes at RIP 0xffffffffc07d1fed.
[  237.823787] RSP: 0018:ffffb59843c43d60 EFLAGS: 00010246
[  237.823788] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff981539e18ac8
[  237.823789] RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff981539e18ac0
[  237.823790] RBP: ffffb59843c43d60 R08: 0000000000000000 R09: ffffb59843c43b58
[  237.823790] R10: ffffb59843c43b50 R11: ffff98153fec68a8 R12: ffffffffc07d2000
[  237.823791] R13: ffff981429558510 R14: 0000000000000000 R15: ffffffffc0848000
[  237.823792] FS:  00007f11f3cc1580(0000) GS:ffff981539e00000(0000) knlGS:0000000000000000
[  237.823793] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  237.823794] CR2: ffffffffc07d1fed CR3: 000000001feee002 CR4: 00000000003706f0
[ 5705.181536] audit: type=1400 audit(1632931211.345:41): apparmor="DENIED" operation="capable" profile="/usr/sbin/cupsd" pid=2786 comm="cupsd" capability=12  capname="net_admin"

反汇编ko文件,使用命令 objdump -S  oops.ko ,可以定位到0x17的地方,正是指针解引用赋值的地方。需要注意的是,想反汇编出源码对应汇编这种格式,需要在编译的时候指定-g,都懂得。

 12 int __init oops_init(void)13 {14    0:   e8 00 00 00 00          call   5 <init_module+0x5>15    5:   55                      push   %rbp16         int * p =NULL;17         pr_warn("will init\n");18    6:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi19 {20    d:   48 89 e5                mov    %rsp,%rbp21         pr_warn("will init\n");22   10:   e8 00 00 00 00          call   15 <init_module+0x15>23         *p=1;24         return 0;25 }26   15:   31 c0                   xor    %eax,%eax27         *p=1;28   17:   c7 04 25 00 00 00 00    movl   $0x1,0x029   1e:   01 00 00 0030 }31   22:   5d                      pop    %rbp32   23:   c3                      ret33 

当然gdb也可以加载ko然后反汇编函数

gdb *.ko(gdb)  disassemble /m oops_init
Dump of assembler code for function oops_init:
warning: Source file is more recent than executable.
12	{0x000000000000003c <+0>:	call   0x41 <oops_init+5>0x0000000000000041 <+5>:	push   %rbp0x0000000000000049 <+13>:	mov    %rsp,%rbp13		int * p =NULL;14		pr_warn("will init\n");0x0000000000000042 <+6>:	mov    $0x0,%rdi0x000000000000004c <+16>:	call   0x51 <oops_init+21>15		*p=1;0x0000000000000053 <+23>:	movl   $0x1,0x016		return 0;17	}0x0000000000000051 <+21>:	xor    %eax,%eax0x000000000000005e <+34>:	pop    %rbp0x000000000000005f <+35>:	ret    End of assembler dump.
(gdb) 

这篇关于Linux内核模块调试一的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139937

相关文章

windows和Linux安装Jmeter与简单使用方式

《windows和Linux安装Jmeter与简单使用方式》:本文主要介绍windows和Linux安装Jmeter与简单使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows和linux安装Jmeter与简单使用一、下载安装包二、JDK安装1.windows设

Kali Linux安装实现教程(亲测有效)

《KaliLinux安装实现教程(亲测有效)》:本文主要介绍KaliLinux安装实现教程(亲测有效),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、下载二、安装总结一、下载1、点http://www.chinasem.cn击链接 Get Kali | Kal

linux服务之NIS账户管理服务方式

《linux服务之NIS账户管理服务方式》:本文主要介绍linux服务之NIS账户管理服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、所需要的软件二、服务器配置1、安装 NIS 服务2、设定 NIS 的域名 (NIS domain name)3、修改主

Linux实现简易版Shell的代码详解

《Linux实现简易版Shell的代码详解》本篇文章,我们将一起踏上一段有趣的旅程,仿照CentOS–Bash的工作流程,实现一个功能虽然简单,但足以让你深刻理解Shell工作原理的迷你Sh... 目录一、程序流程分析二、代码实现1. 打印命令行提示符2. 获取用户输入的命令行3. 命令行解析4. 执行命令

ubuntu16.04如何部署dify? 在Linux上安装部署Dify的技巧

《ubuntu16.04如何部署dify?在Linux上安装部署Dify的技巧》随着云计算和容器技术的快速发展,Docker已经成为现代软件开发和部署的重要工具之一,Dify作为一款优秀的云原生应用... Dify 是一个基于 docker 的工作流管理工具,旨在简化机器学习和数据科学领域的多步骤工作流。它

Python MCPInspector调试思路详解

《PythonMCPInspector调试思路详解》:本文主要介绍PythonMCPInspector调试思路详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋... 目录python-MCPInspector调试1-核心知识点2-思路整理1-核心思路2-核心代码3-参考网址

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Linux系统调试之ltrace工具使用与调试过程

《Linux系统调试之ltrace工具使用与调试过程》:本文主要介绍Linux系统调试之ltrace工具使用与调试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、ltrace 定义与作用二、ltrace 工作原理1. 劫持进程的 PLT/GOT 表2. 重定

Linux区分SSD和机械硬盘的方法总结

《Linux区分SSD和机械硬盘的方法总结》在Linux系统管理中,了解存储设备的类型和特性是至关重要的,不同的存储介质(如固态硬盘SSD和机械硬盘HDD)在性能、可靠性和适用场景上有着显著差异,本文... 目录一、lsblk 命令简介基本用法二、识别磁盘类型的关键参数:ROTA查询 ROTA 参数ROTA

嵌入式Linux之使用设备树驱动GPIO的实现方式

《嵌入式Linux之使用设备树驱动GPIO的实现方式》:本文主要介绍嵌入式Linux之使用设备树驱动GPIO的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、设备树配置1.1 添加 pinctrl 节点1.2 添加 LED 设备节点二、编写驱动程序2.1