0

假设我们想要拦截退出系统调用并在任何进程调用它时在控制台上打印一条消息。为了做到这一点,我们必须编写自己的假出口系统调用,然后让内核调用我们的假出口函数,而不是原来的出口调用。在我们的假退出调用结束时,我们可以调用原始的退出调用。为了做到这一点,我们必须操作系统调用表数组(sys_call_table)。有了 sys_call_table 数组,我们可以操纵它来使 sys_exit 入口点指向我们新的假出口调用。我们必须存储一个指向原始 sys_exit 调用的指针,并在我们完成将消息打印到控制台时调用它。源代码 :

 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <sys/syscall.h>

 extern void *sys_call_table[];

 asmlinkage int (*original_sys_exit)(int);

 asmlinkage int our_fake_exit_function(int error_code)
 {
    /*print message on console every time we
     *are called*/
    printk("HEY! sys_exit called with error_code=%d\n",error_code);

    /*call the original sys_exit*/
    return original_sys_exit(error_code);
 }

 /*this function is called when the module is
 *loaded (initialization)*/
 int init_module()
 {
     /*store reference to the original sys_exit*/
     original_sys_exit=sys_call_table[__NR_exit];

     /*manipulate sys_call_table to call our
      *fake exit function instead
      *of sys_exit*/
     sys_call_table[__NR_exit]=our_fake_exit_function;
 }


 /*this function is called when the module is
   *unloaded*/
 void cleanup_module()
 {
     /*make __NR_exit point to the original
      *sys_exit when our module
      *is unloaded*/
     sys_call_table[__NR_exit]=original_sys_exit;
 }

当我编译这个程序时,我得到了警告:

警告:“sys_call_table”[/home/roiht/driver/one.ko] 未定义!

搜索的时候发现2.5以后的内核版本改变了sys_call表的概念。那么,我的问题是在新内核版本中执行此操作的替代方法是什么?

4

2 回答 2

1

如果已使用 EXPORT_SYMBOL() 在内核中显式导出任何内核变量,则它可以在模块中使用。从内核版本 2.6 开始,sys_call_table 的导出已被删除。因此,如果您想使用这种方法,请显式导出变量。按照惯例,在变量声明之后立即进行导出,但我想从定义了该变量的任何文件中导出也可以。要检查该方法是否有效,只需查看“cat /proc/kallsyms”的输出即可。

捕获退出系统调用的另一种方法是在系统调用执行的 sysenter 部分中放置一个挂钩。在这里查看更多详细信息: http: //articles.manugarg.com/systemcallinlinux2_6.html

于 2012-10-12T20:58:27.230 回答
0

sys_call_table您可以从System.map-xxx与您的内核对应的文件中读取地址。该文件通常在/boot目录中,名称为System.map-<kernel-version>,其中kernel-version是 command 的结果uname -r。您可以使用模块参数将地址传递给您的模块。

于 2013-04-25T09:07:12.720 回答