Это невозможно, потому что таблица системных вызовов (называемых 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
Например) номер системного вызова с вашим, так как для этого не потребуется больше места в памяти. Некоторые архитектуры также могут иметь дыры в таблице системных вызовов (например, 64-битная версия x86), так что вы также можете использовать это.
Вы можете использовать эту технику, если вы разрабатываете новый системный вызов и просто хотите избежать перезагрузки во время экспериментов. Вам нужно будет определить новый системный вызов, найти существующую запись в таблице системных вызовов, а затем заменить ее из вашего модуля.
Делать это из модуля ядра нетривиально, поскольку ядро не экспортирует sys_call_table
в модули начиная с версии 2.6 (последняя версия ядра, в которой был экспортирован этот символ 2.5.41
).
Один из способов обойти это - изменить свое ядро, чтобы экспортировать sys_call_table
символ в модули. Чтобы сделать это, вы должны добавить следующие две строки kernel/kallsyms.c
( не делайте этого на производственных машинах ):
extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);
Другой метод заключается в динамическом поиске таблицы системных вызовов. Вы перебираете память ядра, сравнивая каждое слово с указателем на известную функцию системного вызова. Поскольку вы знаете смещение этого известного системного вызова в таблице, вы можете вычислить начальный адрес таблицы.