Ядро 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: когда вы перехватываете системный вызов, который, как правило, влияет на всю ОС, вы должны беспокоиться о том, как решить проблему безопасного его выполнения: что, если кто-то еще наполовину вызывает системный вызов, а затем вы изменяете / перехватываете коды?

Другие вопросы по тегам