Добавление нового системного вызова в Linux 3.2.x с загружаемым модулем ядра [закрыто]

11

Я хочу добавить новый системный вызов в ядро ​​Linux 3.2.x, но в качестве загружаемого модуля ядра (поскольку я не хочу перекомпилировать ядро ​​снова и снова)

Я прочитал много постов в Интернете, а также в SO, и некоторые места утверждают, что реализация системных вызовов в качестве загружаемых модулей невозможна, в то время как другие говорят, что это возможно.

Что он? Как это сделать, если это возможно?

абхи
источник
Этот вопрос здесь не по теме: Unix & Linux касается использования и администрирования, а не программирования. Вы должны спросить о переполнении стека . Не будьте настолько расплывчаты: дайте ссылку на посты, которые вы нашли в переполнении стека , и объясните, что вы нашли неубедительным или противоречивым.
Жиль "ТАК ... перестать быть злым"
2
Я считаю, что этот вопрос гораздо больше связан с Linux как с ОС, чем с самим программированием. Также очень важно знать, каковы возможности расширения возможностей нашей системы и каковы ее пределы. Это, например, позволяет понять, почему некоторые функции невозможно реализовать в качестве загружаемого модуля и требует исправления ядра. Знание, почему это так, может также дать вам некоторые идеи безопасности против юзабилити-разработчиков ядра. Будет ли этот вопрос больше касаться темы, если OP спросит только, если это возможно, и почему нет, а не как это реализовать?
Кшиштоф Адамски
1
В Списке рассылки ядра Linux было много обсуждений <stroke> flames </ stroke>, например, reiserfs использовал свои собственные системные вызовы, которые не были особенно любимы некоторыми основными разработчиками, включая Линуса. В вашем случае я бы просто использовал ioctl()s для задачи, они легко модульные. Афайк - главная причина, по которой это делается настолько сложно, насколько это возможно, потому что количество системных вызовов является очень жестко закодированной вещью, и никто не хочет хаоса, каким он попадет в картину. Но существует множество интерфейсов ядра для достижения той же функциональности, например, sysfs, ioctls или тому подобное.
Петер - Восстановить Монику

Ответы:

14

Это невозможно, потому что таблица системных вызовов (называемых 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);

Другой метод заключается в динамическом поиске таблицы системных вызовов. Вы перебираете память ядра, сравнивая каждое слово с указателем на известную функцию системного вызова. Поскольку вы знаете смещение этого известного системного вызова в таблице, вы можете вычислить начальный адрес таблицы.

Кшиштоф Адамски
источник
1

К сожалению, вы не можете добавлять системные вызовы в ядро ​​как загружаемые модули. Вы должны взять на себя задачу компиляции ядра каждый раз, когда добавляете новый системный вызов.

PaulDaviesC
источник