Призраки ядра или модули-невидимки




Рисунок5 описание системных вызовов (вместе с аргументами), найденное на просторах Интернета


Перехват syscall'ов осуществляется вполне стандартно и традиционно: ядро экспортирует переменную extern void sys_call_table, указывающую на таблицу системных вызовов, каждый элемент который указывает на соответствующий ему системный вызов (или NULL, если данный системный вызов не реализован). Определения самих системных вызовов содержатся в файле /usr/include/sys/syscall.h. В частности, за mkdir закреплено "имя" SYS_mkdir.

Объявив в модуле переменную "extern void *sys_call_table[]", мы получим доступ ко всем системным вызовам которые только есть (включая нереализованные). old_mkdir = sys_call_table[SYS_mkdir]

заносит в переменную old_mkdir указатель на системный вызов SYS_mkdir, а sys_call_table[SYS_mkdir] = new_mkdir

заменяет его на new_mkdir, который должен располагаться в ядерной области памяти, о разновидностях которой мы поговорим в одноименной врезке.

Внимание: если забыть скопировать new_mkdir в предварительно выделенный блок памяти, то после выгрузки модуля, SYS_mkdir будет указывать на невыделенную область памяти и приложение, вызывавшее функцию mkdir завершится с сигналом 11 – segmentation fault (см. рис. 6), но ядро продолжить функционировать в нормальном режиме и никаких экранов голубой смерти, которыми так славится NT, тут не произойдет. Да, LINUX это вам не Windows! Это _намного_ более крутая и живучая система, способная постоять за себя!

Примечание: на самом деле ядро ничего не экспортирует (в привычной для NT-программистов трактовке этого слова). В каталоге /boot лежит файл System.map, содержащий символьную информацию о всех "публичных" переменных и процедурах ядра. Его-то загрузчик модулей и использует. Если этого файла нет (например, удален администратором по соображениям безопасности), определять адрес таблицы символов приходится эвристическим путем, но это уже тема для отдельной статьи…




Содержание  Назад  Вперед