Неекспортовані символи ядра. Оптимальний підхід до реалізації пошуку символів у ядрі. Виконання, підміна, додавання та приховання системних викликів. Завантаження модуля ядра із програмного коду та з коду іншого модуля. Робота з UNIX-сигналами.
При низкой оригинальности работы "Дослідження можливостей нестандартного використання модулів ядра ОС Linux", Вы можете повысить уникальность этой работы до 80-100%
У Linux є функціональність, доступну при програмуванні модулів ядра, але виходить за рамки традиційного використання модулів і слабо освітлену в документації.У ядрі Linux (починаючи з версії 2.5) може існувати багато незалежних потоків виконання, більше того, ядро Linux є що витісняє (preemptive): код ядра в стані витиснути інші завдання, що виконуються, навіть коли ті працюють у режимі ядра. В користувальницькому просторі звичайно виконується командою kill (або викликом kill() із програмного коду), але тепер аналогічні дії можна виконати й з коду модуля ядра. · модуль ядра ioctl_signal.ko, що буде відправляти зазначений сигнал певному користувальницькому процесу; · діалоговий користувальницький процес ioctl, що вказує модулю ядра ioctl_signal.ko, який саме сигнал відсилати (по номері) і якому процесу (у нашому випадку - це sigreq). Процес ioctl буде передавати команди для ioctl_signal.ko за допомогою викликів ioctl(), які вже розглядалися в статтях, присвячених драйверам символьних пристроїв.Для того, щоб імя із простору ядра можна було «звязати» у модулі, повинні виконуватися дві умови: · імя повинне мати глобальну область видимості (у коді такі імена не повинні оголошуватися як static); · імя повинне бути явно оголошено експортованим, тобто записано параметром макровиклику EXPORT_SYMBOL (ИЛИEXPORT_SYMBOL_GPL). Усе спрацювало, як й очікувалася: адреса оброблювача системного виклику sys_close (експортований ядром й отриманий у ході виконання) збігається зі значенням, прочитаним раніше з /proc/kallsyms. Такий модуль не може бути завантажений, тому що він суперечить правилам цілісності ядра: містить недозволений зовнішній символ (тобто цей символ не експортується ядром для звязування). · модуль, що експортує символ, із вказівкою шляху до файлу модуля, або vmlinux, якщо символ експортується безпосередньо ядром;Експортування забезпечує додатковий рівень контролю для забезпечення цілісності ядра, тому що мінімальна некоректність приводить до повного краху операційної системи, іноді при цьому вона навіть не встигає вивести фінальне повідомлення. Файл call_table.tgz з вихідним кодом модулів можна знайти в розділі "Матеріали для скачивания". Модуль також може використати й всі інші імена (функцій, змінних, структур), перераховані в /proc/kallsyms, якщо зможе сам уважати їх. Повна реалізація даного підходу наведена у файлі mod_rct.c, якому можна знайти в архіві call_table.tgz. У листинге приводиться тільки центральна частина коду, що зчитує й перебирає символи ядра з /proc/kallsyms у пошуках символу sys_call_table (адреса таблиці системних викликів).Ядро надає користувачам (тобто модулям) вызовkallsyms_lookup_name(), що дозволяє виконувати пошук у цій внутрішній структурі. #include static int __init ksys_call_tbl_init( void ) {void** sct = (void**)kallsyms_lookup_name( "sys_call_table" ); printk( " sys_call_table address = %p
", sct ); char table[ 120 ] = "sys_call_table : "; У першому параметрі fn передається покажчик на вашу користувальницьку функцію, що буде последовательновызываться для всіх символів у таблиці ядра, а в другому параметрі data - покажчик на довільний блок даних (параметрів), що буде передаватися в кожен виклик функції fn./* запозичимо з , тут дуже важливо - asmlinkage: asmlinkage long sys_write(unsigned int fd, const char __user *buf, size_t count); */ static asmlinkage long (*sys_write) (unsigned int fd, const char __user *buf, size_t count ); При статическом підході необхідно додати свій файл реалізації arch/i386/kernel/new_calls.c у дерево вихідних кодів ядра Linux і відповідний рядок-запис у таблицю системних викликів arch/i386/kernel/syscall_table.S, а також включити свою реалізацію в зборку ядра, дописавши в arch/i386/kernel/Makefile рядок виду: · obj-y = new_calls.o У поточних версіях цей символ може бути присутнім у таблиці імен ядра (/proc/kallsyms), але він уже не експортується для використання модулями: $ cat /proc/kallsyms | grep "sys_call" c052476b t proc_sys_call_handler c07ab3d8 R sys_call_table Помилка повязана з тим, що таблиця адрес системних викликів перебуває в сегменті тільки для читання, і спроба запису в неї приводить до помилки захисту памяті (звертаємо увагу на символ R): $ cat /proc/kallsyms | grep sys_call_table c07ab3d8 R sys_call_table · робота в ядрі (і з таблицею системних викликів) - украй ризиковане заняття, тому в коді виконується подвійний повторний огляд: адреса оброблювача виклику, знайдена як символ ядра sys_write, рівняється з адресою в позиції __NR_write у таблиці sys_call_table;· у деяких випадках від системи потрібна функціональність, відсутня в ній і забезпечувана подгружаемым модулем ядра; у подібній ситуації було б зручно довантажити такий модуль безпосередньо перед його використанням.
План
4. Зміст розрахунково-пояснювальної записки (перелік питань, які підлягають розробці)
1.1 Робота з UNIX-сигналами 2.1 Пошук символів
2.2 Неекспортовані символи ядра
2.3 Оптимальний підхід до реалізації пошуку символів у ядрі
3.1 Виконання системних викликів 3.2 Підміна системного виклику