当前位置: 首页 > news >正文

卸载驱动模块,内核崩溃排查调试记录

问题
在学习串口子系统,在卸载串口模块的时候,引起内核崩溃。具体的崩溃日志如下:
/mnt/uartdeep # rmmod virtual_uart.ko
[ 23.208560] /home/book/bsp/mcu/uartdeep/virtual_uart_ok/virtual_uart.c virtual_uart_exit 301
[ 23.217242] Before uart_remove_one_port
[ 23.221631] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[ 23.230235] pgd = 94598000
[ 23.233703] [00000000] *pgd=94800831, *pte=00000000, *ppte=00000000
[ 23.243278] Internal error: Oops: 80000007 [#1] PREEMPT SMP ARM
[ 23.249210] Modules linked in: virtual_uart(O-)
[ 23.253784] CPU: 0 PID: 110 Comm: rmmod Tainted: G O 4.1.15 #4
[ 23.260750] Hardware name: Freescale i.MX6 Ultralite (Device Tree)
[ 23.266939] task: 9426aac0 ti: 947ee000 task.ti: 947ee000
[ 23.272345] PC is at 0x0
[ 23.274894] LR is at uart_remove_one_port+0x130/0x150
[ 23.279954] pc : [<00000000>] lr : [<80354ad0>] psr: 200d0013
[ 23.279954] sp : 947efef8 ip : 16fcc000 fp : 00000000
[ 23.291435] r10: 00000000 r9 : 947ee000 r8 : 8000f604
[ 23.296667] r7 : 946fae9c r6 : 00000000 r5 : 946fae00 r4 : 94708010
[ 23.303201] r3 : 00000000 r2 : 00000000 r1 : 600d0013 r0 : 94708010
[ 23.309735] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 23.316876] Control: 10c53c7d Table: 9459806a DAC: 00000015
[ 23.322628] Process rmmod (pid: 110, stack limit = 0x947ee210)
[ 23.328466] Stack: (0x947efef8 to 0x947f0000)
[ 23.332830] fee0: 7f000ad8 7f00093c
[ 23.341017] ff00: 94102244 00000081 8000f604 7f000154 94102210 80385834 94102210 7f00093c
[ 23.349203] ff20: 94102244 80383c80 94102210 7f00093c 94102244 80384410 7f00093c 7e883bf0
[ 23.357392] ff40: 5f6c6175 803839e0 7f000904 7f0004ec 7f000980 800938e4 00001000 74726976
[ 23.365578] ff60: 5f6c6175 74726175 7e883c00 00000001 947ee000 00000000 76f23568 800d5eb8
[ 23.373766] ff80: 00100871 00000000 ffffffff 948025d8 76f23568 00027d38 76dcf5e4 00028a89
[ 23.381952] ffa0: 74726976 8000f480 00028a89 74726976 7e883bf0 00000880 00000000 7e883e88
[ 23.390138] ffc0: 00028a89 74726976 5f6c6175 00000081 00000002 00000000 76f23000 00000000
[ 23.398324] ffe0: 7e883be8 7e883bd8 000289d1 76e08ad2 800d0030 7e883bf0 97fbe821 97fbec21
[ 23.406535] [<80354ad0>] (uart_remove_one_port) from [<7f000154>] (virtual_uart_remove+0x64/0x9c [virtual_uart])
[ 23.416731] [<7f000154>] (virtual_uart_remove [virtual_uart]) from [<80385834>] (platform_drv_remove+0x18/0x30)
[ 23.426838] [<80385834>] (platform_drv_remove) from [<80383c80>] (__device_release_driver+0x70/0xe4)
[ 23.435987] [<80383c80>] (__device_release_driver) from [<80384410>] (driver_detach+0xac/0xb0)
[ 23.444612] [<80384410>] (driver_detach) from [<803839e0>] (bus_remove_driver+0x4c/0xa0)
[ 23.452720] [<803839e0>] (bus_remove_driver) from [<7f0004ec>] (virtual_uart_exit+0x30/0x40 [virtual_uart])
[ 23.462480] [<7f0004ec>] (virtual_uart_exit [virtual_uart]) from [<800938e4>] (SyS_delete_module+0x174/0x1b8)
[ 23.472413] [<800938e4>] (SyS_delete_module) from [<8000f480>] (ret_fast_syscall+0x0/0x3c)
[ 23.480692] Code: bad PC value
[ 23.487156] ---[ end trace f7196ca02fb58b98 ]---
Segmentation fault
/mnt/uartdeep # [ 85.962528] random: nonblocking pool is initialized
由上述日志来看,是由访问非法地址(0地址),造成内核崩溃。而且崩溃的函数是uart_remove_one_port,具体的偏移是0x130
uart_remove_one_port具体实现
该函数的具体承载在文件:drivers/tty/serial/serial_core.c
具体的实现是:

int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
{struct uart_state *state = drv->state + uport->line;struct tty_port *port = &state->port;struct tty_struct *tty;int ret = 0;BUG_ON(in_interrupt());if (state->uart_port != uport)dev_alert(uport->dev, "Removing wrong port: %p != %p\n",state->uart_port, uport);mutex_lock(&port_mutex);/** Mark the port "dead" - this prevents any opens from* succeeding while we shut down the port.*/mutex_lock(&port->mutex);if (!state->uart_port) {mutex_unlock(&port->mutex);ret = -EINVAL;goto out;}uport->flags |= UPF_DEAD;mutex_unlock(&port->mutex);/** Remove the devices from the tty layer*/tty_unregister_device(drv->tty_driver, uport->line);tty = tty_port_tty_get(port);if (tty) {tty_vhangup(port->tty);tty_kref_put(tty);}/** If the port is used as a console, unregister it*/if (uart_console(uport))unregister_console(uport->cons);/** Free the port IO and memory resources, if any.*/if (uport->type != PORT_UNKNOWN)uport->ops->release_port(uport);kfree(uport->tty_groups);/** Indicate that there isn't a port here anymore.*/uport->type = PORT_UNKNOWN;state->uart_port = NULL;
out:mutex_unlock(&port_mutex);return ret;
}

dump日志文件提示,出错点在偏移为0x130(304)字节处
具体的指令与字符换算关系如下(32位系统):
1条c语言指令(210条汇编指令-840字节)
简单语句:2~4条指令 (8~16字节)
函数调用:48条指令(1632字节)
条件判断+分支:612条指令(2448字节)
累计之后,0x130的位置在uport->ops->release_port(uport)处。
该函数是在uart_port结构体的ops变量中。具体的情况如下:

static const struct uart_ops virt_pops = {.tx_empty = virt_tx_empty,.set_mctrl = virt_set_mctrl,.get_mctrl = virt_get_mctrl,.stop_tx = virt_stop_tx,.start_tx = virt_start_tx,.stop_rx = virt_stop_rx,.startup = virt_startup,.shutdown = virt_shutdown,.set_termios = virt_set_termios,.type = virt_type,
};

如上所示,在virt_pops中,没有release_port的实现。由此在调用uart_remove_one_port的时候,由于release_port为空,导致内核崩溃

修正
在virt_pops中,增加release_port的实现:具体如下所示:

static void virt_release_port(struct uart_port *port)
{
}
static const struct uart_ops virt_pops = {.tx_empty = virt_tx_empty,.set_mctrl = virt_set_mctrl,.get_mctrl = virt_get_mctrl,.stop_tx = virt_stop_tx,.start_tx = virt_start_tx,.stop_rx = virt_stop_rx,.startup = virt_startup,.shutdown = virt_shutdown,.set_termios = virt_set_termios,.type = virt_type,.release_port = virt_release_port,
};

如上图所示,增加一个release_port的空实现。之前的问题得以解决。

http://www.hskmm.com/?act=detail&tid=29482

相关文章:

  • 详细介绍:游戏引擎以及游戏开发
  • springboot大学校园旧物捐赠网站(代码+数据库+LW) - 详解
  • DropLoRA 论文浅读:通过动态子空间学习突破 LoRA 的性能瓶颈
  • python基础知识
  • switch语句的简单应用
  • 操作系统CPU和内核思维导图总结
  • defold游戏引擎与lua(teal)编程语言
  • 03 数值类型拓展
  • python如何引用变量的名称
  • Python GIL与No-GIL技术详解
  • fuse.js前端搜索简单使用的三个案例
  • 题解:AT_abc288_h [ABC288Ex] A Nameless Counting Problem
  • 2025 年 CBN 砂轮源头厂家最新推荐榜单:专业实力与客户满意度全景解析及选购指南
  • JDK安装和卸载
  • Python定义一个User类的基本写法
  • 10.12 CSP-S模拟30 改题记录
  • 编译GreatSQL with RocksDB引擎
  • ubuntu源码编译指定版本make
  • 【LeetCode】274. H 指数
  • python之多态
  • Linux安装JDK1.8 tomcat MariaDB(MySQL删减版)
  • Ubuntu系统部署Anaconda环境及Python语言的详细流程
  • python之继承
  • RK3568+MCU实时机器人解决方案 - 教程
  • 做题记录 #2
  • 深度学习开源书籍的技术解析
  • Nginx怎么去做负载均衡?
  • 向量库面试题
  • 02 常用快捷键和指令
  • 深圳公共资源交易中心 www.szzfcg.cn