当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 1 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : 使用模块添加系统调用失败
帖子发表于 : 2010-11-10 10:14 

注册: 2010-11-10 10:03
帖子: 1
送出感谢: 0 次
接收感谢: 0 次
我不想编译内核来添加系统调用,所以采用模块的形式。我模块编译,安装,卸载都可以,但是就是在使用调用自定义系统调用程序的时候返回-1,表示调用失败,是什么原因呢?下面是我的模块:

#include<linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/unistd.h>
#include <linux/time.h>
#include <asm/uaccess.h>
#include<linux/fs.h>
#include <linux/sched.h>
#define __NR_mycall 338

MODULE_LICENSE("GPL");

static int (*anything_saved)(void);

asmlinkage int sys_mycall()
{
printk("hello world\n");
return 100;
}

// 中断描述符表寄存器结构
struct {
unsigned short limit;
unsigned int base;
} __attribute__((packed)) idtr;


// 中断描述符表结构
struct {
unsigned short off1;
unsigned short sel;
unsigned char none, flags;
unsigned short off2;
} __attribute__((packed)) idt;

// 查找sys_call_table的地址
void change_sys_call_table(void)
{
unsigned int sys_call_off;
unsigned int sys_call_table;
char* p;
int i;

// 通过sidt指令获取中断描述符表寄存器的地址,这里面包含有idt表的首地址
asm("sidt %0":"=m"(idtr));
printk(KERN_ALERT "in addr of idtr: %x\n", &idtr);

// 通过idtr里面的idt的首地址+偏移获取0x80中断处理程序的地址,由于idt中的每个门是64位,所以要乘以8,系统调用是0x80项,所以偏移为8*0x80。
memcpy(&idt, idtr.base+8*0x80, sizeof(idt));
//通过这项idt找到system_call的函数地址
sys_call_off=((idt.off2<<16)|idt.off1);
printk(KERN_ALERT "in addr of idt 0x80: %x\n", sys_call_off);

// 从0x80中断服务例程中搜索sys_call_table的地址,即通过找到第一个call指令的机器码8514ff来获取sys_call_table
p=sys_call_off;
for (i=0; i<100; i++)
{
if (p[i] =='\xff' && p[i+1]=='\x14' && p[i+2]=='\x85')
{

sys_call_table=*(unsigned int*)(p+i+3);
unsigned int* sys_call_table_address = &sys_call_table;
printk(KERN_ALERT "in addr of sys_call_table: %x\n", sys_call_table);

//备份系统调用表中修改的那一项
anything_saved = (int(*)(void))(sys_call_table_address[__NR_mycall]);
//将这一项替换成自己的函数
sys_call_table_address[__NR_mycall] = (unsigned long)sys_mycall;

return ;
}
}
}

void undo_sys_call_table(void)
{
unsigned int sys_call_off;
unsigned int sys_call_table;
char* p;
int i;

// 获取中断描述符表寄存器的地址
asm("sidt %0":"=m"(idtr));
printk("out addr of idtr: %x\n", &idtr);

// 获取0x80中断处理程序的地址
memcpy(&idt, idtr.base+8*0x80, sizeof(idt));
sys_call_off=((idt.off2<<16)|idt.off1);
printk(KERN_ALERT "out addr of idt 0x80: %x\n", sys_call_off);

// 从0x80中断服务例程中搜索sys_call_table的地址
p=sys_call_off;
for (i=0; i<100; i++)
{
if (p[i] =='\xff' && p[i+1]=='\x14' && p[i+2]=='\x85')
{
sys_call_table=*(unsigned int*)(p+i+3);
unsigned int* sys_call_table_address = &sys_call_table;
printk(KERN_ALERT "out addr of sys_call_table: %x\n", sys_call_table);
//将系统调用表中这项还原回来
sys_call_table_address[__NR_mycall] = (unsigned long)anything_saved;

return ;
}
}
}

int __init init_addsyscall(void)
{
//模块被insmod后就调用这个函数修改sys_call_table
change_sys_call_table();
return 0;
}

void __exit exit_addsyscall(void)
{
//模块被rmmod后就还原sys_call_table
undo_sys_call_table();
}

module_init(init_addsyscall);
module_exit(exit_addsyscall);

下面是我的调用程序:

#include <linux/time.h>
#include <linux/unistd.h>
#include <stdio.h>

#define __NR_mycall 338

int main()
{
printf("%d\n",syscall(__NR_mycall));

return 0;
}

被这个问题弄晕了 :em20 :em20 ,各位大大帮帮忙啊。


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 1 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 2 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译