Загружаемое программирование модуля ядра и перехват системных вызовов

Предположим, что мы хотим перехватить системный вызов выхода и распечатать сообщение на консоли, когда какой-либо процесс вызывает его. Чтобы сделать это, мы должны написать наш собственный поддельный системный вызов выхода, а затем заставить kernel ​​вызвать нашу функцию поддельного выхода вместо первоначального вызова exit. В конце нашего поддельного вызова выхода мы можем вызвать исходный вызов выхода. Чтобы сделать это, мы должны манипулировать массивом таблиц системных вызовов (sys_call_table). Вооруженный массивом sys_call_table, мы можем манипулировать им, чтобы сделать точку входа sys_exit в наш новый поддельный вызов выхода. Мы должны сохранить указатель на исходный вызов sys_exit и вызвать его, когда мы закончим печать нашего сообщения на консоль. Исходный код :

#include  #include  #include  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] undefined!

Когда я искал, я обнаружил, что версия ядра после 2.5 изменила концепцию таблицы sys_call. Итак, мой вопрос – это альтернативный метод для этого в новой версии ядра?

Любая переменная ядра может использоваться в модуле, если она явно экспортирована в kernel ​​с помощью EXPORT_SYMBOL (). Начиная с версии ядра 2.6 экспорт sys_call_table удаляется. Поэтому, если вы хотите использовать этот подход, явно экспортируйте переменную. Как соглашение, theis export выполняется сразу после объявления переменной, но я предполагаю, что экспорт из любого файла, где будет определена эта переменная, также будет выполняться. Чтобы проверить, работает ли подход, просто просмотрите вывод «cat / proc / kallsyms».

Другим подходом к захвату выхода syscall будет включение крюка в sysenter часть выполнения syscall. Посмотрите здесь, чтобы узнать подробности: http://articles.manugarg.com/systemcallinlinux2_6.html

Вы можете прочитать адрес sys_call_table из файла System.map-xxx соответствующего вашему ядру. Обычно файл находится в каталоге / boot, а имя – System.map- , где kernel-version – результат команды uname -r Вы можете использовать параметр модуля для передачи адреса в ваш модуль.