Це неможливо, оскільки таблиця системних викликів (call sys_call_table
) - це масив статичного розміру. А його розмір визначається в момент компіляції за кількістю зареєстрованих системних дзвінків. Це означає, що немає місця для іншого.
Ви можете перевірити реалізацію, наприклад, архітектури x86 у arch/x86/kernel/syscall_64.c
файлі, де sys_call_table
визначено. Її розмір рівно __NR_syscall_max+1
. __NR_syscall_max
визначається arch/x86/kernel/asm-offsets_64.c
як sizeof(syscalls) - 1
(це номер останнього систематичного виклику), де syscall
знаходиться таблиця з усіма системними дзвінками.
Одне можливе рішення - повторно використовувати деякий існуючий (або застарілий), якщо у вашій архітектурі є такий, див., sys_setaltroot
Наприклад, номер системного виклику з вашим, оскільки це не потребує більше місця в пам'яті. Деякі архітектури також можуть мати отвори в таблиці syscall (наприклад, 64-бітна версія x86), тому ви можете також використовувати це.
Ви можете використовувати цю техніку, якщо ви розробляєте нові syscall і просто хочете уникнути перезавантаження під час експериментів. Вам потрібно буде визначити ваш новий системний виклик, знайти існуючий запис у таблиці syscall та замінити його у своєму модулі.
Зробити це з модуля ядра не тривіально, оскільки ядро не експортує sys_call_table
до модулів, починаючи з версії 2.6 (остання версія ядра, яка експортувала цей символ 2.5.41
).
Один із способів подолати це - змінити ваше ядро на експорт sys_call_table
символу в модулі. Для цього вам потрібно додати наступні два рядки до kernel/kallsyms.c
( не робити цього на виробничих машинах ):
extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);
Ще одна методика - динамічно знаходити таблицю syscall. Ви перебираєте пам'ять ядра, порівнюючи кожне слово із вказівником із відомою функцією системного виклику. Оскільки ви знаєте зміщення цього системного виклику знань у таблиці, ви можете обчислити початкову адресу таблиці.