免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2200 | 回复: 2
打印 上一主题 下一主题

[内核模块] 内核模块中怎么调用带参数的系统调用呢? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-03-08 16:52 |只看该作者 |倒序浏览
  1. 这是内核模块的代码:
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/interrupt.h>
  5. #include <linux/spinlock.h>
  6. #include <linux/proc_fs.h>
  7. #include <linux/msg.h>
  8. #include <linux/delay.h>
  9. #include <asm/fcntl.h>
  10. #include <linux/syscalls.h>
  11. #include <linux/smp_lock.h>
  12. #include <linux/file.h>
  13. #include <linux/kernel.h>
  14. #include <linux/slab.h>
  15. #include <linux/stat.h>
  16. #include <linux/unistd.h>
  17. #include <asm/unistd.h>

  18. #include <linux/sched.h>
  19. #include <linux/time.h>
  20. #include <asm/uaccess.h>


  21. #define __NR_mycall 40//本次模块选择将40号系统调用替换
  22. #define sys_call_table_address 0xc05d2180

  23. unsigned int reset_and_return_cr0(void);
  24. void set_back_cr0(unsigned int val);
  25. int orig_cr0;
  26. unsigned long *sys_call_table = 0;
  27. static long (*anything_saved1)(char *);

  28. long (*org_rmdir)(const char *pathname);
  29. //long (*myread)(int) ;
  30. typedef long (*myread_ptr)(int);
  31. myread_ptr myread = 0;


  32. unsigned int reset_and_return_cr0(void)
  33. {
  34.         unsigned int cr0 = 0;
  35.         unsigned int ret;
  36.         printk("in reset_and_return_cr0!\n");
  37.         asm volatile("movl %%cr0,%%eax":"=a"(cr0));
  38.        
  39.         ret = cr0;
  40.         cr0 &=0xfffeffff;
  41.         asm volatile("movl %%eax,%%cr0"::"a"(cr0));
  42.         printk("out reset_and_return_cr0!\n");
  43.         return ret;
  44. }
  45. void set_back_cr0(unsigned int val)
  46. {
  47.         printk("in set_back_cr0!\n");
  48.         asm volatile("movl %%eax,%%cr0"::"a"(val));
  49.         printk("out set_back_cr0!\n");
  50. }

  51. asmlinkage long sys_mycall(int count)
  52. {

  53.         printk("count= %d\n",count);
  54.         count--;
  55.         if(count <= 0)
  56.         return 0;
  57.        
  58.         myread = (long(*)(int))(sys_call_table[__NR_mycall]);//获取系统调用表中的40号系统调用,也就是本模块中的sys_mycall()调用
  59.         myread(count);//执行调用。
  60.         return 1314;
  61. }
  62. static int init_addsyscall(void)
  63. {
  64.         printk("begin register!\n");
  65.         sys_call_table = (unsigned long*)(sys_call_table_address);
  66.         anything_saved1 = (long(*)(char*))(sys_call_table[__NR_mycall]);
  67.        
  68.         orig_cr0 = reset_and_return_cr0();
  69.         sys_call_table[__NR_mycall] = (unsigned long)&sys_mycall;
  70.         set_back_cr0(orig_cr0);
  71.        
  72.         printk("sys_call= %x ,myread= %x\n",&sys_mycall,myread);
  73.         printk("complete register!\n");
  74.         return 0;
  75. }
  76. static void exit_addsyscall(void)
  77. {
  78.         printk("begin unregister!\n");
  79.        
  80.         orig_cr0 = reset_and_return_cr0();
  81.         sys_call_table[__NR_mycall] = (unsigned long)anything_saved1;
  82.         set_back_cr0(orig_cr0);
  83.        
  84.         printk("complete unregister!\n");
  85. }

  86. MODULE_LICENSE("GPL");
  87. module_init(init_addsyscall);
  88. module_exit(exit_addsyscall);
复制代码
  1. 这是我的测试程序的代码:
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. int main()
  8. {
  9.         int ret;
  10.         char ch[10];
  11.         int fd;
  12.         ret = syscall(40,4);//调用40号系统调用

  13.         printf("the ret = %d\n",ret);
  14.         return 0;
  15. }
复制代码
执行结果如下:

为什么经过myread(count);这次调用的时候count的值不是3,而是一个随机数呢?
求大家帮忙解答一下,难道在内核调用系统调用的时候不能传递参数的吗?还是我的方法有误呢?

论坛徽章:
0
2 [报告]
发表于 2013-03-17 22:36 |只看该作者
本帖最后由 aweii 于 2013-03-17 22:41 编辑

myread = (long(*)(int))(sys_call_table[__NR_mycall]);
myread(count);

直接改成sys_mycall(count);试试呢?

涉及到参数的传递问题,myread是通过寄存器传递,而sys_mycall是通过堆栈,这样就不匹配了,定义myread时要加个asmlinkage的吧。第一次是通过int 0x80调用系统调用的,参数是自动压栈的;第二次通过指针myread调用,默认是通过寄存器传参,参数没有压栈,而sys_mycall还是从堆栈中照count,找到的应该是个什么地址之类的东西,所以显示负数了。

论坛徽章:
0
3 [报告]
发表于 2013-03-18 11:32 |只看该作者
回复 2# aweii


    呵呵 ,我解决了系统调用的函数参数传递的问题,原来在我的myread(count);这里调用的时候在前面用汇编压栈一个参数就可以了,在这里我想小小的总结一下,也不知道对不对,如有错误,请大家帮忙指正,谢谢。

就以myread(count);这个函数的调用来说吧,如果是用户层的函数通过syscall(XX,XX);来调用我sys_mycall的话,那么在syscall()这个函数处理的时候会自动的去指定的寄存器中找参数,而在我的这个内核模块中我通过获取系统调用的入口地址来调用myread(count);的话,就没有通过sys_call()来进行,所以myread(count);这个函数在执行的过程中是没有参数的,所以我在myread(count);调用前用嵌入式汇编语言人工压入了一个参数后,程序就可以在栈里找到自己需要的参数了。
这是我的想法,请大家指正 ,谢谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP