Ядро Linux - добавить системный вызов динамически через модуль
Есть ли способ добавить динамический системный вызов, например, через модуль? Я нашел места, где я могу переопределить существующий системный вызов с помощью модуля, просто изменив sys_call_table[]
массив, чтобы получить мою переопределенную функцию вместо нативной, когда мой модуль установлен, но вы можете сделать это с помощью нового системного вызова и модуля?
3 ответа
Нет, sys_call_table
имеет фиксированный размер:
const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { ...
Лучшее, что вы можете сделать, как вы, вероятно, уже обнаружили, - это перехватывать существующие системные вызовы.
Зак, да можно:D
Хотя sys_call_table имеет фиксированный размер, в некоторых случаях в таблице могут быть свободные позиции
Посмотрите эти ссылки:
lxr.free-electrons.com/source/arch/x86/kernel/syscall_32.c
lxr.free-electrons.com/source/arch/x86/kernel/syscall_64.c
Во-первых, ядро заполняет все позиции sys_call_table указателем на sys_ni_syscall
При компиляции файлы asm/syscalls_32.h и asm/syscalls_64.h создаются на основе следующих таблиц:
lxr.free-electrons.com/source/arch/x86/syscalls/syscall_32.tbl
lxr.free-electrons.com/source/arch/x86/syscalls/syscall_64.tbl
Кратко рассмотрев эти таблицы, вы увидите, что некоторые позиции будут продолжать указывать на sys_ni_syscall, например, на позиции 17, 31, 32, 35, ... в syscall_32.tbl, поскольку они не реализованы.
Поэтому наша единственная задача - идентифицировать эти позиции и "зарегистрировать" наш новый системный вызов.
Я положил что-то похожее на мой мерзавец
https://github.com/MrN0body/rsysadd
Перехват существующего системного вызова (чтобы что-то сделать в ядре) в некоторых случаях является неправильным способом. Например, если ваши драйверы пользовательского пространства должны что-то выполнять в ядре, отправлять туда или читать что-то из ядра?
Обычно для драйверов правильным способом является использование вызова ioctl(), который является всего лишь одним системным вызовом, но может вызывать различные функции ядра или модули драйверов - путем передачи различных параметров через ioctl().
Вышесказанное предназначено для контролируемого пользователем выполнения кода ядра.
Для передачи данных вы можете использовать procfs или драйверы sysfs для связи с ядром.
PS: когда вы перехватываете системный вызов, который, как правило, влияет на всю ОС, вы должны беспокоиться о том, как решить проблему безопасного его выполнения: что, если кто-то еще наполовину вызывает системный вызов, а затем вы изменяете / перехватываете коды?