Вопрос по linux-kernel, module, c, kernel-module, linux – Могу ли я заменить функцию ядра Linux модулем?
========================================================================================================

Я начинаю работу над ядром для небольшого количества моих летних исследований. Мы надеемся внести изменения в TCP, в конкретные расчеты RTT. Я хотел бы заменить разрешение одной из функций в tcp\_input.c на функцию, предоставляемую динамически загружаемым модулем ядра. Я думаю, что это улучшило бы скорость, с которой мы можем разрабатывать и распространять модификацию.

Интересующая меня функция была объявлена как статическая, однако я перекомпилировал ядро с нестатической функцией и экспортировал ее в EXPORT\_SYMBOL. Это означает, что функция теперь доступна для других модулей / частей ядра. Я подтвердил это с помощью "cat / proc / kallsyms".

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

Спасибо!

Такой же как[**Overriding functionality with modules in Linux kernel**](https://stackoverflow.com/questions/290898/overriding-functionality-with-modules-in-linux-kernel)

Редактировать:  

Это был мой возможный подход.  

Учитывая следующую функцию (которую я хотел переопределить, и не экспортируется):

изменить так:

Это переопределяет ожидаемый идентификатор функции вместо этого как указатель функции (который может быть вызван аналогичным образом), указывающий на исходную реализацию. EXPORT\_SYMBOL () делает адрес глобально доступным, поэтому мы можем изменить его из модуля (или другого места в ядре).

Теперь вы можете написать модуль ядра со следующей формой:

Этот модуль заменяет оригинальную реализацию динамически загружаемой версией. После выгрузки исходная ссылка (и реализация) восстанавливается. В моем конкретном случае я предоставил новый оценщик для RTT в TCP. Используя модуль, я могу вносить небольшие изменения и перезапускать тестирование без необходимости перекомпиляции и перезагрузки ядра.

Я не уверен, что это сработает - я полагаю, что разрешение символов для внутренних вызовов функции, которую вы хотите заменить, уже будет выполнено к моменту загрузки вашего модуля.

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



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

Я ввел свою собственную функцию в ядро, переписав первые пару байтов кода с помощью перехода, указывающего на мою пользовательскую функцию. Как только вызывается настоящая функция, она переходит к моей функции, которая после того, как она выполнила свою работу, вызвала исходную функцию.

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

Это действительно простой принцип, но очень эффективный. Конечно, реальное решение будет использовать блокировки, чтобы никто не вызывал функцию, пока вы ее перезаписываете.

Повеселись!



Вы можете попробовать использовать[Ksplice](https://www.ksplice.com/) - вам даже не нужно делать его не статичным.



Я думаю, что вы хотите[KProbe](https://www.redhat.com/magazine/005mar05/features/kprobes/).

Другой способ, о котором упомянул caf, - добавить хук в исходную процедуру и зарегистрировать / отменить хук в модуле.