linux 强制删除内核模块(由于初始化错误导致rmmo..
时间:2010-11-16 来源:jiaxin_liu88
|
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命令,卸载之前的模块了。 实验环境 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删除。
相关阅读 更多 +