Создайте shim `.so`, чтобы переименовать символы существующего` .so` - PullRequest
0 голосов
/ 03 января 2019

У меня есть готовая общая библиотека .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 не поддерживает переименование символов в динамической библиотеке.Проблема, подтвержденная этим почтовым потоком .

Подводя итог, я задаю следующие вопросы:

  1. Существует ли существующий утилит, способный генерировать такую ​​общую библиотеку шимов для указанного.so файл?
  2. Или, может быть, есть лучший способ решить эту несовместимость между пакетами CentOS и Debian OpenSSL, при условии, что я не хочу изменять ни предоставленную сторонней стороной libjniopenssl.so, ни предоставленную ОС копиюOpenSSL?
...