• 添加linux系统调用的两种方式


    原文:https://blog.csdn.net/sdulibh/article/details/51889279

    向linux内核添加系统调用,一是通过编译内核添加,二是通过内核模块的方式添加:

    一:编译内核

    第一步,下载内核版本。(我用的是2.6.39.2)
                   然后在指定的目录下解压。
    -------------------------------------------------------------------------------------
    第二步,在arch/x86/include/asm/unistd_32.h
    文件中添加系统调用号。
    -------------------------------------------------------------------------------------
    第三步,在arch/x86/kernel/syscall_table.s
    文件中添加相应的表项。
    -------------------------------------------------------------------------------------
    第四步:实现系统调用的服务历程。
     理论上,这个函数的位置没有固定,最好加在arch/x86/kernel/目录
    下的文件里面。我这次是加在arch/x86/kernel/sys_i386_32.c文件中
    -------------------------------------------------------------------------------------
    第五步:重新编译内核。
    5.1,内核使用默认的配置,make menuconfig直接选择exit退出
    5.2,使用如下命令编译内核
    -------------------------------------------------------------------------------------
    第六步:用户态测试系统调用。(注意内核安装好后,重启后选择新的内核)
    运行结果:
    -------------------------------------------------------------------------------------

    二: 使用内核模块方式添加简单系统调用 

    1,为什么要使用内核模块的方式添加系统调用?

        1.1,编译内核的方式费时间,一般的PC机都要两三个小时。
        1.2,不方便调试,一旦出现问题前面的工作都前功尽弃。
    -------------------------------------------------------
    2,首先要获取系统调用表sys_call_table的地址(虚拟地址)
       因为sys_call_table在内核中没有导出,可以使用如下命令查看。
     
    1. cat /proc/kallsyms | grep sys_call_tables
    注意点:当我把模块在一个机子上运行成功后,如果移植到另外一个机子上马上就会出现
            错误,为什么呢?因为每个机子上sys_call_table的地址可能不一样。
    -------------------------------------------------------
    3,需要查看预留的系统调用号。
      可以到arch/x86/include/asm/unistd.h文件中查看预留的系统调用号。
    可以看出223就是一个预留的系统调用号。
    -------------------------------------------------------
    4,实例:

    1. #include <linux/init.h>
    2. #include <linux/module.h>
    3. #include <linux/kernel.h>
    4. #include <linux/unistd.h>
    5. #include <asm/uaccess.h>
    6. #include <linux/sched.h>
    7. #define my_syscall_num 223
    8. //如下的这个值要到你机子上查。cat /proc/kallsyms | grep sys_call_table
    9. #define sys_call_table_adress 0xc1511160
    10. unsigned int clear_and_return_cr0(void);
    11. void setback_cr0(unsigned int val);
    12. asmlinkage long sys_mycall(void);
    13. int orig_cr0;
    14. unsigned long *sys_call_table = 0;
    15. static int (*anything_saved)(void);
    16. unsigned int clear_and_return_cr0(void)
    17. {
    18.  unsigned int cr0 = 0;
    19.  unsigned int ret;
    20.  asm("movl %%cr0, %%eax":"=a"(cr0));
    21.  ret = cr0;
    22.  cr0 &= 0xfffeffff;
    23.  asm("movl %%eax, %%cr0"::"a"(cr0));
    24.  return ret;
    25. }
    26. void setback_cr0(unsigned int val) //读取val的值到eax寄存器,再将eax寄存器的值放入cr0中
    27. {
    28.  asm volatile("movl %%eax, %%cr0"::"a"(val));
    29. }
    30. static int __init init_addsyscall(void)
    31. {
    32.  printk("hello, kernel ");
    33.  sys_call_table = (unsigned long *)sys_call_table_adress;//获取系统调用服务首地址
    34.  anything_saved = (int(*)(void)) (sys_call_table[my_syscall_num]);//保存原始系统调用的地址
    35.  orig_cr0 = clear_and_return_cr0();//设置cr0可更改
    36.  sys_call_table[my_syscall_num] = (unsigned long)&sys_mycall;//更改原始的系统调用服务地址
    37.  setback_cr0(orig_cr0);//设置为原始的只读cr0
    38.  return 0;
    39. }
    40. asmlinkage long sys_mycall(void)
    41. {
    42.  printk("This is my_syscall! ");
    43.  return current->pid;
    44. }
    45. static void __exit exit_addsyscall(void)
    46. {
    47.  //设置cr0中对sys_call_table的更改权限。
    48.  orig_cr0 = clear_and_return_cr0();//设置cr0可更改
    49.  //恢复原有的中断向量表中的函数指针的值。
    50.  sys_call_table[my_syscall_num] = (unsigned long)anything_saved;
    51.  
    52.  //恢复原有的cr0的值
    53.  setback_cr0(orig_cr0);
    54.  printk("call exit ");
    55. }
    56. module_init(init_addsyscall);
    57. module_exit(exit_addsyscall);
    58. MODULE_LICENSE("GPL");
    -------------------------------------------------------
    5,将模块插入成功后,剩下的就是在用户态下测试是否成功了。
  • 相关阅读:
    Advanced Developer's Blog
    图片文字识别
    Unit test resources
    SpringBoot-mvn插件
    flask中使用proto3
    QTA-qtaf自动化测试实践
    AttributeError: module 'virtualenv' has no attribute 'create_environment'
    qtaf dick 报错 NameError: name 'dict_values' is not defined
    24点python实现
    mysql在win下移植
  • 原文地址:https://www.cnblogs.com/wangliangblog/p/9234463.html
Copyright © 2020-2023  润新知