Почему LD_PRELOAD работает с системными вызовами? - PullRequest
3 голосов
/ 28 февраля 2020

Идея LD_PRELOAD состоит в том, чтобы загрузить общую библиотеку перед исходной общей библиотекой, например, я могу скомпилировать mylib.so, чтобы загрузить ее до libc.so, поэтому, когда процесс хочет использовать printf, он ищет в so, который загружается один за другим и находит его в mylib.so (потому что этот so был загружен первым) вместо libc.so, поэтому он использует printf в mylib.so вместо printf в libc.so.

Я понимаю, почему это работает с функциями, которые реализованы в so, например printf в libc.so.

Но когда я хочу подключить функцию write или другая функция syscall, почему она работает? Процесс не ищет функцию в so, он идет непосредственно к ядру.

  1. Работает ли LD_PRELOAD в двоичном файле, который статически компилируется? Почему? В этом воспроизведении { ссылка } упомянул, что LD PRELOAD не работает со статически двоичным кодом

  2. Почему LD_PRELOAD работает с двоичным файлом, скомпилированным динамически для создания хуков на системные вызовы?

Архитектура ARM.

1 Ответ

6 голосов
/ 28 февраля 2020

Процесс не ищет функцию в so, он идет непосредственно в ядро.

Неверно, используемые вами функции системного вызова (read(), write() , ...) все lib c оболочки вокруг реальных системных вызовов, даже функция generi c syscall(). Вот код для функции write(), например. Единственный способ go напрямую в ядро ​​из вашей программы - вручную запустить системный вызов (см. Ниже).

Работает ли LD_PRELOAD в двоичном файле, который статически компилируется? Почему?

Нет, это не так. Двоичный файл stati c не нуждается в динамическом разрешении какого-либо символа, поэтому загрузчик динамического c не вызывается для разрешения обычных символов библиотечной функции.

Почему LD_PRELOAD работает с двоичный файл, скомпилированный динамически для создания ловушек на системных вызовах?

Потому что это обычные функции lib c, не более и не менее.


Единственный способ вручную Для вызова системного вызова без прохождения через библиотеку C (и, следовательно, без выполнения разрешения символов), кроме статической компиляции, используется встроенная сборка . Вы можете взглянуть на man 2 syscall, чтобы увидеть, какие регистры и инструкции использовать. Например, в ARM AArch64 вы можете вызвать системный вызов, загрузив номер системного вызова в регистр x8, параметры от x0 до x5, а затем выполнив инструкцию svc #0.

...