天天看点

关于内核符号表(Kernel-Symbol-Table)

驱动也是存在于内核空间的,它的每一个函数每一个变量都会有对应的符号,这部分符号也可以称作内核符号,它们不导出(EXPORT_SYMBOL)就只能为自身所用,导出后就可以成为公用,对于导出的那部分内核符号就是我们常说的内核符号表。insmod的时候并不是所有的函数都得到内核符号表去寻找对应的符号,每一个驱动在自已的分配的空间里也会存在一份符号表,里面有关于这个驱动里使用到的变量以及函数的一些符号,首先驱动会在这里面找,如果发现找不到就会去公共内核符号表中搜索,搜索到了则该模块加载成功,搜索不到则该模块加载失败。

对于2.4内核和2.6内核的内核符号表是有区别的,2.4内核默认情况下模块中的非静态全局变量以及非静态函数在模块加载后自动导出到内核符号表中,而2.6内核默认情况下是不会自动导出的,需要显式调用宏EXPORT_SYMBOL才能导出。导出的符号前面一般标注有r标记。可以通过nm -l xx.ko来查看一个模块里的符号情况。或者通过查看内核符号表文件也行。对于2.4是:cat /proc/ksyms,对于2.6是:cat /proc/kallsyms。   对于一个模块来讲,如果仅依靠自身就可以实现自已的功能,那么可以不需要要导出任何符号,只有其他模块中需要使用到该模块提供的函数时,就必须要进行导出操作。

由此启发,因为LKM中所存取的每一个符号(像函数名)也会被列在内核符号表中,有时候我们可以看内核符表就可以看到LKM调用的那些函数,如果这个LKM为非法目的,那么我们可以杀掉这个LKM.

如何使你的KLM符号不列在/proc/ksyms中,LKM开发者可以用如下的常用代码来声明他们模块的符号:

static struct symbol_table module_syms= {

/*定义自已的符号表*/

#include <linux/symtab_begin.h>

/*我们想引用的符号表*/

.........

};

register_symtab(&module_syms);

/*实际的注册工作*/

我们并不需要对外公开我们的符号,所以我们只要用如下的语句就可以了:

register_symtab(NULL);

这条语句必须放在init_module()函数中!

继续阅读