|
OpenBSD可加载内核模块编程完全指南(1) 绪论
这篇文章我说明在openbsd上如何进行内核编程,以下句子来自lkm手册页: "可加载内核模块可以允许系统管理员在一台运行着的系统上动
态的增加或删除功能模块,它同时可以帮助软件工程师们为内核增加新的功能而根本就不需要重起计算机就可以测试他们开发的程序."
当然,像众多系统的lkm一样,它存在一定的安全隐患,哈哈,其实这也是我写这篇文章给大家的原因:)它提供了更广泛的空间给恶意的
superroot,其实也就是已经得到系统管理员权限的我们。我们利用lkm可以驾驭整个系统而不会轻易被发现. 同样的, 如果你系统的 securelevel在0级一行的话就不能加载或卸载模块了,如果你要使系统在进入securemode之前可以加载模块,可以编辑 /etc/rc.securelevel文件,添加相应的入口.
总览
/dev/lkm设备与用户的交互通过ioctl(2)系列系统调用来进行. 主要是一些工具如modload,modunload和modstat等来控制模块的加载
和卸载以及模块的状态. lkm接口定义了五种不同的模块类型:
系统调用模块 虚拟文件系统模块 设备驱动模块 可执行程序解释器模块 其它模块 一个普通的模块包括三个主要部分: 1) 内核入口和出口的处理(也就是当模块被加载,被卸载时的动作).
2) 一个外部入口点, 当模块用modload程序被加载的时候需要用到
3) 模块的主体, 包含函数代码等.
对于其他类型的模块来说,它需要开发人员提供严格的控制和当内核模块卸载的时候对内核原有的状态的保存.
对于模块的支持必须用'option LKM'编译进内核的配置文件.模块需要支持默认的openBSD 2.9的内核.通常,内核空间的数据接口都被提供
给了模块来操作.后面 就有一个lkm设备的例子.
每个类型的模块的内部数据结构里面都存在一个宏用来加载自己.也就类似模块本身模块名的东东,它被指定在内核数据结构中,和模块的一些
特殊数据如sysent这样 的针对系统调用模块的结构在一起.
让我们看看一些例子吧.
★系统调用模块.
这里我们将增加一个新的系统调用printf()的整型和字符串参数.它的原型如下:
int syscall(int, char *)
内核内部定义的一个lkm的syscall结构如下: strUCt lkm_syscall { MODTYPE lkm_type; int lkm_ver; char *lkm_name; u_long lkm_offset; /* 保存/分配 内存空间 */ struct sysent *lkm_sysent; struct sysent lkm_oldent; /*保存原调用,用于lkm的卸载 */ };
现在我们已经有了一个简单的模块框架了(应该叫LM_SYSCALL),lkm的版本,模块名,都在系统调用表里存在一个相应的入口.这样我们有
|