linux 强制删除内核模块(由于初始化错误导致rmmod不能删除)

/Files/csjiaxin/force_rmmod.rar
在内核模块的插入过程中,如果初始化函数发生错误,比如内核崩溃,则使用rmmod 会提示
ERROR: Module export is in use
 
解决方法如下:
 
struct module{
enum module_state state;
/* Reference counts */
 struct module_ref ref[NR_CPUS];
}
 
enum module_state
{
 MODULE_STATE_LIVE,
 MODULE_STATE_COMING,
 MODULE_STATE_GOING,
};
 
在执行初始化函数前,内核会将为此插入模块新分配的module结构的引用计数初始化为1,状态state设置为MODULE_STATE_COMING,由于初始化失败,所以module结构的引用计数和状态就停留于此。
为在rmmod->delete_module->sys_delete_module中有以下的判断语句:
/* Doing init or already dying? */
 if (mod->state != MODULE_STATE_LIVE) {
  /* FIXME: if (force), slam module count and wake up
                   waiter --RR */
  DEBUGP("%s already dying\n", mod->name);
  ret = -EBUSY;
  goto out;
 }
if (!forced && module_refcount(mod) != 0)
  wait_for_zero_refcount(mod);
则可以看出只能卸载状态state为MODULE_STATE_LIVE,ref数组中所有CPU引用计数之和为0的模块,这就导致rmmod无法卸载由于初始化函数崩溃的模块。
 
明白了原理,具体的实现就比较容易了:
1 root@lstar-desktop:~/force_rmmod# cat /proc/kallsyms | grep modules
c069b9a0 d modules
2 编写另外一个内核模块,去操作内核所有module组成的链表(表头变量即为modules,我们在第一步已看到他的地址) 其中module_name,是传递过来的需要卸载的内核模块的名称

        struct list_head *modules=(struct list_head *)0xc069b9a0;
        struct module *mod=0;
        struct module *list_mod;
        int i;
        int zero=0;
     
        list_for_each_entry(list_mod,modules,list){
                if(strcmp(list_mod->name,module_name) == 0)
                  mod=list_mod;
        }
   
   
        mod->state=MODULE_STATE_LIVE;
        for (i = 0; i < NR_CPUS; i++){
                                      mod->ref[i].count=*(local_t *)&zero;
        }
  
 
将这个内核模块使用insmod插入,执行到初始化函数的时候,搜索modules链表,找到所要操作的module对象,修改其引用计数及状态,结束之后就可以使用rmmod命令,卸载之前的模块了。
 
***********************
今天在写内核模块时,又发现了一个由于卸载过程module_exit指定的函数失败导致内核模块不能卸载,则需要多修改几个条件,需要将module的init和exit修改为NULL,则可以完成卸载。
1 mod->init=0;
2 mod->exit=0;
 
实验环境 ubuntu9.04 kernel2.6.28-19,源码见附件
 
可以完善的地方,
1 内核模块直接从/proc/kallsyms中读取modules地址
2 在将状态设置为MODULE_STATE_LIVE和清空引用计数后,可以直接通过
/* Free a module, remove from lists, etc (must hold module_mutex). */
static void free_module(struct module *mod)
函数删除内核模块,则无需调用 rmmod删除。

posted on 2010-12-14 16:00 lstar 阅读(13342) 评论(1)  编辑 收藏 引用

评论

# re: linux 强制删除内核模块(由于初始化错误导致rmmod不能删除) 2012-06-06 17:42 cat1579

如果编译的时候加了 -f 选项,删除的时候 可以用 rmmod modname -f 来删除  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2012年6月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

统计

常用链接

留言簿

文章档案

搜索

最新评论