У меня есть готовая общая библиотека .so
(назовем ее libjniopenssl.so
).Он был построен третьей стороной на Debian Linux
с OpenSSL 1.0.1k-3+deb8u4
.Мне пришлось запустить libjniopenssl.so
на CentOS
с пакетом OpenSSL 1.0.2k
.Несмотря на то, что версии OpenSSL
немного отличаются, используемый libjniopenssl.so
API не изменился между 1.0.1k
и 1.0.2k
- поэтому я ожидал, что они будут совместимы с исходным кодом и двоичным кодом для моего сценария.К сожалению, просто запуск libjniopenssl.so
на CentOS
не работает.
libjniopenssl.so
загружается JVM
через System.loadLibrary
, но происходит сбой со следующей ошибкой при запуске на CentOS
:
Unable to load libjniopenssl: java.lang.UnsatisfiedLinkError: /tmp/jna-112200956/jna6604950569974562639.tmp:
libcrypto.so.1.0.0: cannot open shared object file: No such file or directory
Причина проста, такого файла libcrypto.so.1.0.0
на CentOS
нет, потому что OpenSSL 1.0.2k 16.el7
обеспечивает только следующие .so
:
$ ls -l /lib64/libcrypto*
lrwxrwxrwx. 1 root root 19 Jun 5 2018 /lib64/libcrypto.so.10 -> libcrypto.so.1.0.2k
-rwxr-xr-x. 1 root root 2512832 Apr 11 2018 /lib64/libcrypto.so.1.0.2k
Для некоторыхпричина CentOS
пакет намеренно переименован в .so
имя файла по умолчанию libcrypto.so.1.0.0
в libcrypto.so.1.0.2k
, даже если при компиляции этой версии из source используется имя libcrypto.so.1.0.0
.
В этом сообщении об ошибке предлагается попытаться создать символическую ссылку с именем /lib64/libcrypto.so.1.0.0
, которая указывает на /lib64/libcrypto.so.1.0.2k
Это привело к следующей ошибке во время выполнения:
Unable to load libjniopenssl: java.lang.UnsatisfiedLinkError: /tmp/jna-112200956/jna2564265718506275007.tmp:
/lib64/libcrypto.so.1.0.0: version `OPENSSL_1.0.0' not found (required by /tmp/jna-112200956/jna2564265718506275007.tmp)
Проверка libjniopenssl.so
показала, что существуют следующие символы, на которые ссылаются из OpenSSL
:
$ readelf -Ws libjniopenssl.so
Symbol table '.dynsym' contains 40 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000e98 0 SECTION LOCAL DEFAULT 9
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND EVP_CIPHER_CTX_init@OPENSSL_1.0.0 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND malloc@GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND OPENSSL_add_all_algorithms_noconf@OPENSSL_1.0.0 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND HMAC_CTX_cleanup@OPENSSL_1.0.0 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND EVP_CipherUpdate@OPENSSL_1.0.0 (2)
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND ERR_load_crypto_strings@OPENSSL_1.0.0 (2)
11: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.2.5 (3)
12: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
13: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (3)
14: 0000000000000000 0 FUNC GLOBAL DEFAULT UND HMAC_CTX_init@OPENSSL_1.0.0 (2)
15: 0000000000000000 0 FUNC GLOBAL DEFAULT UND HMAC_Final@OPENSSL_1.0.0 (2)
16: 0000000000000000 0 FUNC GLOBAL DEFAULT UND EVP_sha1@OPENSSL_1.0.0 (2)
17: 0000000000000000 0 FUNC GLOBAL DEFAULT UND HMAC_Init_ex@OPENSSL_1.0.0 (2)
18: 0000000000000000 0 FUNC GLOBAL DEFAULT UND HMAC_Update@OPENSSL_1.0.0 (2)
19: 0000000000000000 0 FUNC GLOBAL DEFAULT UND EVP_CIPHER_CTX_cleanup@OPENSSL_1.0.0 (2)
20: 0000000000000000 0 FUNC GLOBAL DEFAULT UND EVP_MD_size@OPENSSL_1.0.0 (2)
21: 0000000000000000 0 FUNC GLOBAL DEFAULT UND EVP_aes_128_ctr@OPENSSL_1.0.1 (4)
Но libcrypto.so.1.0.2k
на CentOS
имеет символы с другим постфиксом, например:
readelf -Ws /lib64/libcrypto.so.1.0.2k | grep -iE "EVP_CIPHER_CTX_init"
705: 000000000012a6b0 151 FUNC GLOBAL DEFAULT 13 EVP_CIPHER_CTX_init@@libcrypto.so.10
Итак, для CentOS
postfix равен @@libcrypto.so.10
, но libjniopenssl.so
был связан с общей библиотекой, которая имеет символыс постфиксом @OPENSSL_1.0.0
.Вероятно, поэтому просто добавление символической ссылки не работает.
Дальнейшие исследования показали, что Debian
версия OpenSSL 1.0.1k
имеет , включает много патчей , включая тот, который добавляет версионность символов .Он был представлен только в OpenSSL 1.1.0
, но был портирован обратно кем-то, кто предоставляет пакет Debian для 1.0.1
.
В противоположность этому пакет CentOS
OpenSSL 1.0.2k
не содержит этого патча для управления версиями символов (ноони включают в себя другие патчи из 1.1.0
в соответствии с символами в .so
).
Я мог бы пересобрать libjniopenssl.so
на CentOS
против его копии OpenSSL
, но это фактически включало в себя поддержание (сборку, хранение, развертывание) собственной копии libjniopenssl.so
, которая фактически поступает из стороннего git-репозитория.Мне не нравится решение по перестройке, поэтому я ищу более элегантное.Но я должен сказать, что пересборка - это то, что рекомендуется на CentOS
форуме.
Одно решение, о котором я могу подумать, - это создание во время сборки или развертывания специального shim libcrypto.so.1.0.0
(на основе целевой копии, предоставленной системой libcrypto
), которая переименовывает символы по желанию libjniopenssl.so
, но под капотом она будет переводить все вызовы в исходную систему, предоставленную libcrypto.so.1.0.2k
.
В общемЯ ищу какой-то инструмент или набор инструментов, который способен автоматически генерировать такой «shim / adapter / proxy» .so
из указанной «реализации» .so
, но с возможностью переопределения некоторых или всех символов.Я обнаружил, что есть инструмент objcopy
, который имеет --redefine-symbol old=new
, но он точно не выполняет то, что я хочу: я не хочу копировать какой-либо код из оригинального .so
, я хочу перевести вызовы воригинальная "реализация" .so
.
UPD : при выполнении локального эксперимента objcopy
не поддерживает переименование символов в динамической библиотеке.Проблема, подтвержденная этим почтовым потоком .
Подводя итог, я задаю следующие вопросы:
- Существует ли существующий утилит, способный генерировать такую общую библиотеку шимов для указанного
.so
файл? - Или, может быть, есть лучший способ решить эту несовместимость между пакетами
CentOS
и Debian
OpenSSL
, при условии, что я не хочу изменять ни предоставленную сторонней стороной libjniopenssl.so
, ни предоставленную ОС копиюOpenSSL
?