这里主要是用到int register_module_notifier(struct notifier_block *nb)的通知链机制,当有ko加载时,notifier函数被调用;
模块的四种状态
enum module_state {
MODULE_STATE_LIVE, /* Normal state. */
MODULE_STATE_COMING, /* Full formed, running module_init. */
MODULE_STATE_GOING, /* Going away. */
MODULE_STATE_UNFORMED, /* Still setting it up. */
};
当模块加载时,状态位MODULE_STATE_COMING;
register.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
int success_int ( void )
{
return 0;
}
void success_exit ( void )
{
}
int module_handler ( struct notifier_block *nblock, unsigned long code, void *_param )
{
unsigned long flags;
struct module *param = _param;
//定义一个自旋锁,上锁前禁止中断
DEFINE_SPINLOCK(module_event_spinlock);
//开自旋锁
spin_lock_irqsave(&module_event_spinlock, flags);
switch ( param->state )
{
case MODULE_STATE_COMING:
printk("Detected insertion of module '%s', neutralizing init and exit routines\n", param->name);
//改变ko初始化的入口和出口函数
param->init = success_int;
param->exit = success_exit;
break;
default:
break;
}
//释放自旋锁
spin_unlock_irqrestore(&module_event_spinlock, flags);
return NOTIFY_DONE;
}
static struct notifier_block nb = {
.notifier_call = module_handler,
.priority = INT_MAX,
};
static int __init register_init(void)
{
printk("Function --> %s\n",__func__);
register_module_notifier(&nb);
return 0;
}
static void __exit register_exit(void)
{
unregister_module_notifier(&nb);
printk("the funciton is: %s\n",__func__);
}
module_init(register_init);
module_exit(register_exit)
Makefile:
obj-m := register.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
实际效果:
[60187.494863] Function --> register_init
[60303.177354] Detected insertion of module 'lkm1', neutralizing init and exit routines
可以看到已经检测到ko的加载过程,并且替换入口函数,原lkm1的模块初始化函数并没有被执行;