You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86架构Linux内核中如何通过内存地址定位故障内核模块名称

基于故障地址识别Linux内核模块名称的实现方案

核心思路

你不需要依赖kernel/module/internal.h(该文件是内核内部私有头文件,外部模块无法引用),直接利用公开的内核接口和全局变量就能实现需求:

  • 用modules全局链表遍历所有已加载模块
  • 持有module_mutex锁避免遍历过程中模块动态加载/卸载引发的竞态
  • 检查地址是否落在模块的核心段(core)或初始化段(init)范围内

完整实现代码

#include <linux/module.h>
#include <linux/list.h>
#include <linux/mutex.h>

void get_mod_name(unsigned long addr)
{
    struct module *mod;

    // 锁定模块链表,防止遍历期间模块被加载/卸载
    mutex_lock(&module_mutex);

    // 遍历所有已加载模块
    list_for_each_entry(mod, &modules, list) {
        bool addr_in_mod = false;

        // 适配不同内核版本的地址范围检查逻辑
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
        // 5.x及以上内核:使用mem数组存储核心/初始化段信息
        // 检查核心段
        if (addr >= (unsigned long)mod->mem[MODULE_CORE].base &&
            addr < (unsigned long)mod->mem[MODULE_CORE].base + mod->mem[MODULE_CORE].size) {
            addr_in_mod = true;
        }
        // 检查初始化段(仅当该段未被释放时)
        if (!addr_in_mod && mod->mem[MODULE_INIT].size > 0 &&
            addr >= (unsigned long)mod->mem[MODULE_INIT].base &&
            addr < (unsigned long)mod->mem[MODULE_INIT].base + mod->mem[MODULE_INIT].size) {
            addr_in_mod = true;
        }
#else
        // 5.x以下内核:使用core_addr/core_size、init_addr/init_size字段
        if (addr >= (unsigned long)mod->core_addr &&
            addr < (unsigned long)mod->core_addr + mod->core_size) {
            addr_in_mod = true;
        }
        if (!addr_in_mod && mod->init_size > 0 &&
            addr >= (unsigned long)mod->init_addr &&
            addr < (unsigned long)mod->init_addr + mod->init_size) {
            addr_in_mod = true;
        }
#endif

        if (addr_in_mod) {
            printk(KERN_WARNING "Module's name is: %s", mod->name);
            // 找到目标模块后立即解锁返回,避免无效遍历
            mutex_unlock(&module_mutex);
            return;
        }
    }

    mutex_unlock(&module_mutex);
    printk(KERN_WARNING "No module found for address 0x%lx", addr);
}

关键注意事项

  • 必须加锁:module_mutex是内核保护模块链表的全局互斥锁,遍历前必须锁定,否则会因链表动态修改引发内核崩溃。
  • 版本适配:不同内核版本中struct module的地址存储字段不同,通过LINUX_VERSION_CODE宏做分支处理,保证兼容性。
  • 初始化段判断:模块加载完成后,初始化段(init)可能被内核释放,因此需要先判断其大小是否大于0再检查地址范围。
  • 避免私有头文件:kernel/module/internal.h是内核内部代码专用,外部模块包含会导致编译错误,所有需要的公开定义都在<linux/module.h>中。

内容的提问来源于stack exchange,提问作者Vinicius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 06:06:00