1) Unter Ubuntu 10.04 mit OpenSSL 0.9.8:

1) Unter Ubuntu 10.04 mit OpenSSL 0.9.8:

Ich versuche, ein Programm zu kompilieren progund es mit der Betaversion 1.0.2 von OpenSSL zu verknüpfen, die aus den Quellen erstellt und in installiert wurde /usr/local/ssl-1.0.2. Auf einem älteren System mit 0.9.8 funktioniert dies ohne allzu große Probleme. Auf einem neueren System mit installierter Version 1.0.1 ist dies etwas aufwändiger. Ich frage mich, warum.

1) Unter Ubuntu 10.04 mit OpenSSL 0.9.8:

Hier sind die Schritte, die ich zum Kompilieren und Verknüpfen mit 1.0.2 befolge.

$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto

=> Es werden nur 0.9.8-Dateien angezeigt, also füge ich den Pfad zu den 1.0.2-Dateien hinzu …

$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0008000000008000) => /lib/i686/cmov/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0004000000000000) => /lib/i586/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0002000000000000) => /lib/i486/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6) => /lib/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6) => /usr/lib/libcrypto.so.0.9.8
 libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so

Und so kann ich kompilieren prog...

$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0x0083b000)

... und es ist korrekt mit 1.0.2 verknüpft.

2) Unter Debian Wheezy mit OpenSSL 1.0.1:

Dieselben Schritte, anderes Ergebnis.

$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0

Ebenso füge ich den Pfad zu 1.0.2 hinzu...

$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0
 libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so

Dann versuche ich zu kompilieren...

$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0 (0xb7591000)

Aber hier ist es nicht mit 1.0.2 verknüpft. Der Bibliothekspfad zur Kompilierungszeit ist korrekt (angegeben mit -L, gccwürde andernfalls fehlschlagen, da einige in verwendete Funktionen progspezifisch für 1.0.2 sind), aber nicht der zur Laufzeit.

3) Wie man es auf Wheezy zum Laufen bringt

Mit oder ohne Laufen ldconfig /usr/local/ssl-1.0.2/lib:

$ gcc -o prog ... -Wl,--rpath=/usr/local/ssl-1.0.2/lib -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0xb7592000)

Alternativ können Sie export LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/libvor dem Ausführen ausführen gcc.

Was ich gerne wissen würde

Ich habe die von mr.spuratic vorgeschlagenen Schritte ausgeführt und LD_DEBUG=libs ./progfestgestellt, dass die Pfade in nachgeschlagen wurden /etc/ld.so.cache. Ich habe die Datei geöffnet und festgestellt, dass die Reihenfolge, in der .so nachgeschlagen werden, der Ausgabe von entspricht ldconfig -p.

Die eigentliche Frage ist also:

  • Warum steht die Datei 1.0.2 in 1) ganz oben auf der Liste von ldconfig, aber nicht in 2)? Reiner Zufall? Verwirrung, weil die Dateien 1.0.1 und 1.0.2 das gleiche Suffix haben? ("1.0.0")

Oder anders gesagt,

  • Warum sind die in 3) hinzugefügten Flags in 1) nicht erforderlich?

Antwort1

Beim Kompilieren/Linken mit einem nicht standardmäßigen Paket müssen Sie drei Dinge beachten:

  • Header (normalerweise CFLAGS)
  • Bibliothekspfad zur Kompilierungszeit (normalerweise LDFLAGS)
  • Laufzeitbibliothekspfad (rPfadüber LDFLAGS, LD_RUN_PATH, LD_LIBRARY_PATHoder ld.so.conf)

Sie haben nicht gesagt, was proges ist, also kann ich nicht sagen, wie gut sich die Konfiguration verhält (oder ob es Autoconf verwendet?). Ich habe viele gesehen, die nur die ersten beiden Schritte zuverlässig ausführen.

Während der Verknüpfungsphase ist die Reihenfolge der Bibliothekspfade relevant. Vorausgesetzt, Sie verwenden die GNU-Toolchain (gcc und binutils), können Sie wahrscheinlich sehen, was passiert, indem Sie CFLAGSvorher configure(oder möglicherweise direkt Makefile) Folgendes festlegen:

export CFLAGS="-Wl,-t"

Dadurch wird die -tTrace-Option an den Linker übergeben. Möglicherweise müssen Sie dem Make-Befehl V=1oder hinzufügen VERBOSE=1, wenn Sie während des Make-Befehls nur knappe „CC“- und „LD“-Zeilen als Ausgabe erhalten.)

Zur Laufzeit können Sie sehen, was ld.soversucht wird, indem Sie sorgfältig einstellen LD_DEBUG, zB

LD_DEBUG=libs ./myprog

(oder versuchen Sie es mit den Werten filesoder symbolsfür weitere Einzelheiten)

Um alle drei Parameter zur Build-Zeit korrekt anzugeben, sollten Sie in der Lage sein, Folgendes zu tun:

  • export CFLAGS="-I/usr/local/ssl-1.0.2/include"
  • export LDFLAGS="-L/usr/local/ssl-1.0.2/lib -R/usr/local/ssl-1.0.2/lib"

dann neu konfigurieren/neu kompilieren.

Sie verwenden --openssldiranstelle der konventionelleren Version --prefix(ich empfehle letztere und auch nur, make install_swwenn Sie die etwa 1000 Manpages und Symlinks, die Ihnen eine Standardinstallation bietet, nicht benötigen). Dies kann Teil des Problems sein. Aus irgendeinem Grund ist bekannt, dass die von Ihnen angezeigten .so-Bibliotheken ld.sokein Versionssuffix haben (z. B. .so.1.0.2), ein richtiges " make install" hätte dies für Sie einrichten sollen (über das link-sharedZiel im Haupt- Makefile).

Die -ROption weist den Linker an, einen RPATH in die ausführbare Ausgabe für die spezifische OpenSSL-Bibliothek einzubetten, sodass er nicht auf den Standard angewiesen ist, den der Runtime-Linker ( ld.so) normalerweise bereitstellen würde. Sie können vorhandene Binärdateien ändern mitchrpathstattdessen.

Dies entspricht mehr oder weniger dem Exportieren LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib. Weitere Informationen zu RPATH und dem zugehörigen RUNPATH finden Sie hier:http://blog.tremily.us/posts/rpath/

Als letzten Ausweg könnten Sie OpenSSL möglicherweise ohne „shared“ oder mit „noshared“ erstellen. Dadurch erhalten Sie statische Bibliotheken, die dieses Problem nicht haben (aber möglicherweise andere Probleme haben, z. B. bei der Verwendung innerhalb von ELF .so, was zu PIC/PIE-Problemen führt).


Basierend auf den aktualisierten Details glaube ich, dass das Problem darin liegt, dass 1.0.1 und 1.0.2beta beide das .so-Versionssuffix (SONAME) auf 1.0.0 setzen. Auf dem ersten System mit nur 0.9.8 verursacht dies keine Probleme; auf dem zweiten mit 1.0.1 und 1.0.2, beide als 1.0.0 versioniert, gilt aufgrund der ld.so.{conf,d}Reihenfolge „das erste Match gewinnt“. Denken Sie daran, dass ldder Linker zur Kompilierungszeit ein anderes Programm ist als ld.soder Linker zur Laufzeit und ein anderes Verhalten aufweisen kann (was normalerweise zu Symbolfehlern oder Schlimmerem führt, wie Sie gesehen haben).

$ cd /usr/local/src/openssl/openssl/1.0.2beta1
$ readelf -a libssl.so | grep SONAME
0x0000000e (SONAME)                     Library soname: [libssl.so.1.0.0]

$ cat verchk.c
int main(int argc, char *argv[]) {
    printf("build: %s\n",OPENSSL_VERSION_TEXT);
    printf("run  : %s\n",SSLeay_version(SSLEAY_VERSION));
    return 0;
}

$ gcc -Wall  -I/usr/local/src/openssl/openssl-1.0.2-beta1/include \
    -Wl,-rpath /usr/local/src/openssl/openssl-1.0.2-beta1/ \
    -o verchk /usr/local/src/openssl/openssl-1.0.2-beta1/libcrypto.so verchk.c

$ ./verchk
build: OpenSSL 1.0.2-beta1 24 Feb 2014
run  : OpenSSL 1.0.2-beta1 24 Feb 2014

$ grep SHLIB_M...R= Makefile
SHLIB_MAJOR=1
SHLIB_MINOR=0.0

Aktualisieren OpenSSL-1.1 hat einige Änderungen auf API-Ebene vorgenommen; der obige Code kann mit v1.1-Headern und älteren Bibliotheken () nicht kompiliert werden undefined reference to `OpenSSL_version'.

SSLeay_version()ist mittlerweile veraltet und OPENSSL_API_COMPATkann (abhängig von ) mit #define-d auf die richtige API-Funktion gesetzt werden OpenSSL_version().

Antwort2

Befindet sich der Pfad der neuen Bibliothek in einer der darin enthaltenen Dateien /etc/ld.so.conf.d? Nächster Lauf:-

#ldconfig -v

um den Cache neu zu erstellen. Wenn Sie schnell sind, sollten Sie die neue Bibliothek in der langen Liste sehen, die sie ausgibt (oder sie an grepoder weiterleiten less).

Vielleicht war der Pfad bereits auf dem ersten Server vorhanden, aber nicht auf dem zweiten?

verwandte Informationen