动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > C/C++教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ C/C++教程 ]的信息

本月文章推荐
.信号(signal)介绍.
.C++中对浮点数的格式化显示.
.显卡计算.
.自定义快速报表的打印预览窗口.
.数据结构学习(C++)之稀疏矩阵.
.C语言高效编程的的四招技巧.
.剖析Windows任务管理器开发原理与.
.在C++Builder中创建DLL.
.在 C++中处理错误.
.Win 95/NT下OpenGL编程原理.
.高质量C++/C编程指南 --&nb.
.C++箴言:只要可能就用const.
.从当前的浏览器取得当前URL.
.原创:一个c++写的发牌程序.
.C语言初学者入门讲座 第六讲 分支.
.入门教程:C++中的const限定修饰符.
.Visual C++中动态链接库技术浅谈.
.学C++不得不看的一篇文章.
.C++的iostream标准库介绍(3).
.C语言初学者入门讲座 第十三讲 联.

OpenBSD 可加载内核模块编程完全指南

发表日期:2008-3-8 |



  绪论

这篇文章我说明在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的版本,模块名,都在系统调用表里存在一个相应的入口.这样我们有

了一个指向结构sysent的模块框架
我们将用MOD_SYSCALL宏来安装它:

MOD_SYSCALL("ourcall", -1, &newcallent)

我们来分析一下上面的宏,很明显,模块名为"ourcall",用来标示模块,还有一个作用就是我们利用modstat命令时会显示出来.-1代表我们

的syscall该插入的位置,在这个
宏当中的-1的意思是我们不用关心位置具体在什么地方,它会被分配到一个空的位置.最后一个字段newcallent是一个指向sysent的结构,

它包含了我们系统调用的相应的数
据.
除此之外我们还需要一个句柄用来加载和卸载内核模块,好,在这个例子中我用'hi'来加载,用'bye'来卸载.这对我们调试程序很有帮助.句柄可

以是相同的函数或者单个函数,
假如没有定义句柄,那么lkm_nofunc()会简单的返回0,这个模块是没有加载卸载的,也就失去了作用.

我们模块的外部入口点是ourcall():

int

ourcall(lkmtp, cmd, ver)
struct lkm_table *lkmtp;
int cmd;
int ver;
{
DISPATCH(lkmtp, cmd, ver, ourcall_handler, ourcall_handler, lkm_nofunc)
}

这个句柄可以用来加载,卸载模块.第四个参数我们用作加载操作,第五个参数用作卸载操作,第六个参数是状态函数(在此例中没有用到).
ok!完整的系统调用模块代码如下(syscall.c):

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/cdefs.h>
#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/exec.h>
#include <sys/lkm.h>
#include <sys/proc.h>
#include <sys/syscallargs.h>


/* 定义我们自己的系统调用原型 */
int newcall __P((struct proc *p, void *uap, int *retval));

/*
* 所有的系统调用都有三个参数: 一个指向proc结构的结构指针,一个空指针指向参
* 数本身和一个返回指针.下面,我们定义这些参数的结构.假如你只有一个参数,则
* 只需要一个入口就可以了.
*/

struct newcall_args{
syscallarg(int) value;
syscallarg(char *) msg;
};

/*
* 下面这个结构定义了我们的系统调用.第一个参数是系统调用的参数数目,第二个参数
* 是参数的大小,第三个参数是我们的系统调用的代码了,呵呵:)
*/

static struct sysent newcallent = {
2, sizeof(struct newcall_args), newcall
};

/*
* 好了,到了我们的syscall的核心结构了,呵呵:)
* 第一个参数是syscall的名称,ioctl()调用用它来查询syscall.第二个参数告诉我们
* syscall的位置.这里你可以输入数字,或者-1来让系统自动分配.第三个参数指向一个
* sysent结构的指针.
*/

MOD_SYSCALL("ourcall", -1, &newcallent);

/*
* 要使我们的模块正常运行我们还要用到以下函数.此函数类似Linux的lkm里面的init_module
* 和cleanup_module.
* 它通过一个指向lkm_table结构的指针来完成我们给定的动作.检查cmd的值来判定该加载
* 什么样的句柄.当我们利用模块来增加一个系统调用的时候,这儿没有专门的句柄来操作.
* 当然,我们hacking kernel的时候是不会用例如"hi"和"bye"这样的简单的句柄的,我们
* 需要改变系统调用.我们现在是说明原理,其实大同小异:)
*/

static int
ourcall_handler(lkmtp, cmd)
struct lkm_table *lkmtp;
int cmd;
{
if (cmd == LKM_E_LOAD)
printf("hi!n");
else if (cmd == LKM_E_UNLOAD)
printf("bye!n");

return(0);
}

/*
* 下面就是我们模块的外部入口点,也就是我们的系统调用的主体.
* 象上面那样我们通过判定一个cmd所匹配的句柄来描述动作的执行.我们也可以通过一个版本号
* 答应一个模块兼容以后版本内核的源码,以保证向下的兼容性.
* DISPATCH宏通过三个参数来表示动作的加载,卸载和状态.我们看下面例子,对于加载和卸载
* 我们用共享函数ourcall_handler().对于状态(当增加系统调用的时候就用不到它了)我们
* 用lkm_nofunc(),该函数仅仅简单的返回0.
*/

int
ourcall(lkmtp, cmd, ver)
struct lkm_table *lkmtp;
int cmd;
int ver;
{
DISPATCH(lkmtp, cmd, ver, ourcall_handler, ourcall_handler, lkm_nofunc)

}

/*
* 最后对于我们的系统调用应该有主体代码,该调用干了什么之类.
*/

int
newcall(p, v, retval)
struct proc *p;
void *v;
int *retval;
{
struct newcall_args *uap = v;

printf("%d %sn", SCARG(uap, value), SCARG(uap, msg));
return(0);
}

ok!我们编译安装它:
# cc -D_KERNEL -I/sys -c syscall.c
# modload -o ourcall.o -e ourcall syscall.o
Module loaded as ID 0
#

-o参数指定输出文件名,这和gcc的-o选项是一样的.-e参数指定我们的外部标示,最后一个参数就是输入文件.好,我们用modstat看看我们的

模块有没有被成功加载:
# modstat
Type Id Off Loadaddr Size Info Rev Module Name
SYSCALL 0 210 e0b92000 0002 e0b93008 2 ourcall
#

以上显示需要注重一下'off'字段,它标示了该模块在system call表里面的位置.这在创建系统调用的时候需要用到.我们可以通过dmesg命令

的输出'hi'来验证我们
的模块正确的加载运行了:
# dmesg tail -2
hi!
DDB symbols added: 150060 bytes
#

好,现在让我们来看一个测试我们刚才新的系统调用的简单程序(calltest.c):
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#
上一篇:POSIX 线程详解(1) 人气:490
下一篇:PE文件格式分析心得 人气:579
浏览全部C/C++的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-10-10 企业网站智能管理系统(TZIMS) v6
2008-10-10 拓文asp.net网站内容管理系统 v6
2008-10-10 动网论坛PHP版 v2.0++ Build 081
2008-10-10 免费时代CMS v5.0
2008-10-10 wodig第四季中文DIGG社区 v4.1 b
2008-10-10 老Y文章管理系统 v2.2 bulid 081
2008-10-10 魔法盒动感相册 ASP+SQL版 v2.0
2008-10-10 Asoft签到管理系统 v3.0 Pack1
2008-10-10 哥特人音乐网潮流留言本 v1.1
2008-10-11 联系人分组工具 v1.1 中文破解版
2008-10-11 FaceMelter变脸 v2.0 汉化破解版
2008-10-11 PathTracker道路跟踪仪 v1.2 破解
2008-10-11 Rooms手机聊天室 v0.6.7 破解版
2008-10-11 RemoteDesktop远程桌面 v1.0 破解
2008-10-11 ProRemote远程调音台 v1.0.1 破解
2008-10-11 PicShare照片共享 v1.0.0 破解版
2008-10-11 Photogene照片编辑器 v1.5 汉化破
2008-10-11 WriteRoom共享文档 v1.0 破解版
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | 广告代码 | js/vbs加密 | md5加密 | 进制转换 | UTF-8 转换工具 | Html转换js | Html转换asp | Html转换php | Html转换perl
实用工具:汉字翻译拼音 | 拼音字典 | 符号对照表 | 个税计算 | 实时汇率查询换算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 | 国家代码与域名缩写 | 文字加密解密 | 健康查询 | 万年历 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵
SEO対策 中国語教室 ホームページ作成