путь
![]() | Эта статья может быть слишком технической для понимания большинства читателей . ( декабрь 2022 г. ) |
В вычислениях rpath обозначает во время выполнения, путь поиска жестко запрограммированный в исполняемом файле или библиотеке . динамической компоновки Загрузчики используют rpath для поиска необходимых библиотек.
В частности, он кодирует путь к общим библиотекам в заголовок исполняемого файла (или другой общей библиотеки). Это значение заголовка RPATH (названное так в стандартах заголовков исполняемых и связываемых форматов ) может либо переопределять, либо дополнять системные пути поиска с динамическим связыванием по умолчанию.
Путь к исполняемому файлу или общей библиотеке — это необязательная запись в .dynamic
раздел исполняемого файла ELF или разделяемых библиотек с типом DT_RPATH
, называемый DT_RPATH
атрибут. Компоновщик может сохранить его там во время компоновки. Такие инструменты, как chrpath
и patchelf
может создать или изменить запись позже.
Использование записи DT_RPATH динамическим компоновщиком
[ редактировать ]Различные динамические компоновщики для ELF реализуют использование DT_RPATH
атрибутировать по-разному.
GNU ld.so
[ редактировать ]Динамический компоновщик библиотеки GNU C ищет общие библиотеки в следующих местах по порядку: [1]
- Пути (разделенные двоеточиями) в
DT_RPATH
Атрибут динамического раздела двоичного файла, если он присутствует, иDT_RUNPATH
атрибут не существует. - Пути (разделенные двоеточиями) в переменной среды
LD_LIBRARY_PATH
, если только исполняемый файл не являетсяsetuid/setgid
двоичный, и в этом случае он игнорируется.LD_LIBRARY_PATH
можно переопределить, вызвав динамический компоновщик с опцией--library-path
(например/lib/ld-linux.so.2 --library-path $HOME/mylibs myprogram
). - Пути (разделенные двоеточиями) в
DT_RUNPATH
Атрибут динамического раздела двоичного файла, если он присутствует. - Поиск на основе
ldconfig
файл кэша (часто находится по адресу/etc/ld.so.cache
), который содержит скомпилированный список библиотек-кандидатов, ранее найденных в пути к расширенной библиотеке (установленном/etc/ld.so.conf
). Однако если двоичный файл был связан с-z nodefaultlib
параметр компоновщика, библиотеки в путях к библиотекам по умолчанию пропускаются. - В доверенном пути по умолчанию
/lib
, а потом/usr/lib
. Если двоичный файл был связан с-z nodefaultlib
компоновщика, этот шаг пропускается.
Если не удастся найти общую библиотеку во всех этих местах, возникнет ошибка «невозможно открыть файл общего объекта: нет такого файла или каталога».
Примечания:
readelf -d <binary_name> | grep 'R.*PATH'
отображает RPATH или RUNPATH двоичного файла. в gcc можно указать RPATH с помощью Например,-Wl,-rpath,/custom/rpath/
.- Вариант
--inhibit-rpath LIST
динамического компоновщика инструктирует его игнорироватьDT_RPATH
иDT_RUNPATH
атрибуты имен объектов в LIST. Чтобы указать основную программу в списке LIST, укажите пустую строку. - Библиотеки, указанные переменной среды
LD_PRELOAD
а затем те, которые перечислены в/etc/ld.so.preload
загружаются до начала поиска. Таким образом, предварительная загрузка может использоваться для замены некоторых (или всех) обычных функций запрошенной библиотеки или ее можно просто использовать для предоставления библиотеки, которая в противном случае не была бы найдена. - Статические библиотеки просматриваются и связываются с файлом ELF во время компоновки и не просматриваются во время выполнения.
Роль GNU ld
[ редактировать ]GNU Linker (GNU ld) реализует функцию, называемую «new-dtags», которую можно использовать для вставки rpath с более низким приоритетом, чем путь LD_LIBRARY_PATH
переменная среды.
[2]
Если в компоновщике включена функция new-dtags ( --enable-new-dtags
), ГНУ ld
, помимо установки DT_RPATH
атрибут, также устанавливает DT_RUNPATH
атрибут той же строки. Если во время выполнения динамический компоновщик обнаруживает DT_RUNPATH
атрибут, он игнорирует значение атрибута DT_RPATH
атрибут, в результате которого LD_LIBRARY_PATH
проверяется в первую очередь, а пути в DT_RUNPATH
атрибуты ищутся только после этого.
Динамический компоновщик ld не выполняет поиск DT_RUNPATH
места для транзитивных зависимостей, в отличие от DT_RPATH
. [3]
Вместо указания -rpath
для компоновщика, переменная среды LD_RUN_PATH
можно настроить на тот же эффект.
Солярис лд.со
[ редактировать ]Динамический компоновщик Solaris , в частности /lib/ld.so
SunOS 5.8 и подобных системах ищет библиотеки в каталогах, указанных в переменной LD_LIBRARY_PATH , прежде чем просматривать DT_RPATH
атрибут. Sun Microsystems была первой [ нужна ссылка ] ввести динамическую загрузку библиотеки. Позже Sun добавила в ld опцию rpath и использовала ее в основных библиотеках в качестве дополнительной функции безопасности. GNU ld сделал то же самое для поддержки динамических библиотек в стиле Sun.
Пример
[ редактировать ]![]() | Эта статья содержит инструкции, советы и инструкции . ( август 2018 г. ) |
![]() | Актуальность конкретной информации в (или ранее в) этой статье или разделе оспаривается . ( май 2024 г. ) |
$ cc -shared -Wl,-soname,termcap.so.4,-rpath,/lib/termcap.so.4 -o termcap.so.4
$ objdump -x termcap.so.4
NEEDED libc.so.6
SONAME termcap.so.4
RPATH /lib/termcap.so.4
В этом примере GNU или Sun ld (ld.so) ОТКАЗЫВАЮТСЯ загружать termcap для программы, которая в нем нуждается, если файл termcap.so
находится в /lib/
и назван termcap.so.4
. LD_LIBRARY_PATH игнорируется. Если /lib/termcap.so.4
удаляется для исправления, оболочка умирает (нельзя загрузить альтернативную termcap.so
и нужен аварийный диск, но и если новый termcap.so.4
имеет RPATH /lib, ld.so откажется использовать его для загрузки, если он не забит /lib/termcap.so.4
). Но есть еще одна проблема: копировать некоторые библиотеки в /lib
поскольку они «используются», что еще больше ограничивает потенциальный тестер lib. Более того, SONAME termcap.so.4 против. SONAME termcap.so означает программы, требующие базового termcap.so
отказано, поскольку указанная выше библиотека удалила доступ ABI к базовой поддержке.
$ cc -shared -Wl,-soname,libtermcap.so.2 -o libtermcap.so.2
$ objdump -x termcap.so.2
NEEDED libc.so.6
SONAME termcap.so.2
Старый Linux/Sun использовал вышеописанное, что позволяло пользователю указать любой программе использовать любую termcap.so
они указывают в LD_LIBRARY_PATH или то, что можно найти в /usr/local/lib(n), используя такие правила поиска, как ld.so.conf
. Однако GNU ld всегда использует /lib
или /usr/lib
независимо от того, что было раньше LD_LIBRARY_PATH , поэтому сначала /lib/termcap.so
перенесен в /usr/local/lib
и это упомянуто в ld.so.conf
, что позволяет использовать перемещение libs
и ld.so.conf
или использование LD_LIBRARY_PATH для использования. Предпочтительной практикой является использование " SONAME termcap.so » и заставить программы проверять версию (все библиотеки поддерживают это), чтобы использовать доступные функции, но в старых выпусках это часто пропускалось из-за низкой скорости вычислений и нехватки времени для правильного кода.
При этом тщательно протестируйте подобные вещи на конкретной платформе, прежде чем принимать решение полагаться на них. Сегодняшние администраторы релизов не гарантируют соблюдения прошлых рекомендаций или документации. Некоторые разновидности UNIX компонуются и загружаются совершенно по-другому. rpath специфичен для ld, поставляемого с определенным дистрибутивом.
Наконец, как уже было сказано, rpath — это функция безопасности, однако «обязательный контроль доступа» (MAC) и другие методы могут быть столь же или даже более эффективными, чем rpath, для контроля чтения и записи библиотек.
Контроль над rpath с помощью современных компиляторов часто практически невозможен из-за длинных и запутанных сценариев make(1). Хуже того, некоторые сценарии сборки игнорируют --disable-rpath, хотя они и представляют его как опцию. Исправление сценариев сборки в каждой нечетной программе, подлежащей компиляции, заняло бы много времени, утомило и, вероятно, неосуществимо.
Простая «обертка» sh(1) может вызывать настоящий ld с именем ld.bin. Обертка может фильтровать вход/выход -rpath перед вызовом ld.
#!/bin/sh
# - filter ld options here -
ld.bin $opts
Однако обратите внимание, что некоторые сборки неправильно используют rpath вместо rpath-link или LD_LIBRARY_PATH или $(TOP)/dir/foo.so для поиска промежуточных продуктов, которые остаются в каталоге сборки - таким образом, обратно требуется rpath в конечном продукте, что является новой проблемой, касающейся того, «что такое rpath».
Соображения безопасности
[ редактировать ]Использование rpath, а также runpath может представлять угрозу безопасности, если применяемое значение включает каталоги, находящиеся под контролем злоумышленника. Это может включать случаи, когда определенное значение явно ссылается на доступное для записи местонахождение злоумышленника, а также случаи, когда используется относительный путь либо через наличие . или .. через $ORIGIN и т. д. или если оператор каталога остается незаполненным. В частности, это может позволить использовать двоичные файлы setUID, где используется небезопасный путь. Это можно использовать, чтобы заставить двоичный файл загрузить вредоносные библиотеки из того или иного каталога, находящегося под контролем злоумышленника.
Ссылки
[ редактировать ]- ^ «Команда Linux/Unix: ld.so» . man7.org . Проверено 19 февраля 2018 г.
- ^ «Общие библиотеки: проблемы распространения и системы сборки» . Официальный сайт компилятора Haskell . Проверено 4 апреля 2019 г.
- ^ «Ошибка № 1253638 «динамический компоновщик не использует DT_RUNPATH для транзита...: Ошибки: Пакет Eglibc: Ubuntu» . 21 ноября 2013 г.
Внешние ссылки
[ редактировать ]- chrpath — инструмент для изменения
DT_RPATH
атрибут исполняемого файла и преобразовать его вDT_RUNPATH
атрибут - Порт devel/chrpath для FreeBSD — инструмент для изменения DT_RPATH в существующих двоичных файлах ELF.
- patchELF — небольшая утилита для изменения динамического компоновщика и
DT_RUNPATH
атрибут исполняемых файлов ELF . - [1] - Документ об атаке на компоновщик времени выполнения, включая атаки на DT_RPATH.