0

Assume that we want to intercept the exit system call and print a message on the console when any process invokes it. In order to do this, we have to write our own fake exit system call, then make the kernel call our fake exit function instead of the original exit call. At the end of our fake exit call, we can invoke the original exit call. In order to do this, we must manipulate the system call table array (sys_call_table). Armed with the sys_call_table array, we can manipulate it to make the sys_exit entry point to our new fake exit call. We must store a pointer to the original sys_exit call and call it when we are done printing our message to the console. Source code :

 #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;
 }

When I compile this program I got warning :

WARNING: "sys_call_table" [/home/roiht/driver/one.ko] undefined!

As I did search, I found that kernel version after 2.5 changed the concept of sys_call table. So, my question is what is alternative method to do this in new kernel version ?

mpromonet
  • 11,326
  • 43
  • 62
  • 91
Rohit
  • 23
  • 2
  • 10

2 Answers2

1

Any kernel variable can be used in a module if it has been explicitly exported in the kernel using EXPORT_SYMBOL(). Since kernel version 2.6, export for sys_call_table has been removed. So if you want to use this approach, explicitly export the variable. As a convention, theis export is done right after the variable declaration, but I guess exporting from any file where this variable is defined will also do. To check if the approach worked, simply look in the output of "cat /proc/kallsyms".

Another approach to capture the exit syscall will be to put a hook in the sysenter part of syscall execution. Look here for more details: http://articles.manugarg.com/systemcallinlinux2_6.html

pareshverma91
  • 804
  • 2
  • 8
  • 14
0

You can read the address of sys_call_table from System.map-xxx file corresponding to your kernel. The file is usually in /boot directory, and the name is System.map-<kernel-version>, where kernel-version is the result of command uname -r. You can use module parameter to pass the address to your module.

pevik
  • 4,523
  • 3
  • 33
  • 44