Utiliser la libc alternative avec les hacks ld-linux.so; méthode plus propre?

13

J'ai un système hérité avec une très vieille glibc, que nous ne pouvons pas mettre à niveau sans encourir une montagne de tests / validation.

J'ai dû exécuter plusieurs fois de nouveaux programmes (tels que Java 1.7) sur ce système. J'ai opté pour une solution chroot, où je regroupe toutes les bibliothèques nécessaires et exécute un service dans un chroot.

Le chroot est cependant très limitant, et je préfère essayer de résoudre le problème avec LD_LIBRARY_PATH. Malheureusement, je reçois une erreur libc.so.6: cannot handle TLS datalorsque j'essaye.

Il s'avère que j'ai aussi besoin /lib/ld-linux.so.2du chroot. Cela marche:

LD_LIBRARY_PATH=/home/chroot/lib /home/chroot/lib/ld-linux.so.2 /home/chroot/bin/program

Cependant, javadéjoue mon astuce en inspectant /proc/self/cmdlinepour déterminer d'où charger ses bibliothèques, ce qui échoue si le binaire n'a pas été nommé 'bin / java'. Java s'exécute également au démarrage, ce qui complique encore les choses.

Dans une dernière tentative pour que cela fonctionne, j'ai ouvert le binaire java avec un éditeur hexadécimal et remplacé la chaîne /lib/ld-linux.so.2par /home/chroot/ld.so(et en ai fait un lien symbolique ld-linux.so.2), et cela a fonctionné!

Mais je pense que tout le monde serait d'accord pour dire que c'est une tâche énorme de réécrire le chemin de chaque nouveau binaire vers un chemin absolu du système imbriqué.

Quelqu'un connaît-il une façon plus propre d'utiliser un chemin de bibliothèque personnalisé, y compris un ld-linux.so personnalisé?

sans données
la source

Réponses:

12

Le chemin vers le chargeur est compilé dans le binaire comme vous l'avez découvert avec votre éditeur hexadécimal. En fait, vous avez eu de la chance que l'édition du binaire fonctionne directement car les deux /lib/ld-linux.so.2et /home/chroot/ld.sosont de la même longueur. Les longueurs de ces chaînes sont également en binaire et vous pouvez provoquer des problèmes subtils si vous modifiez les chaînes directement.

Si vous finissez par suivre la route, vous devriez jeter un œil à quelque chose comme patchelf pour mettre à jour l'interpréteur. Cela vous permettrait de changer définitivement l'interprète rapidement et en toute sécurité.

gmjosack
la source
Ce n'était pas de la chance, je savais que je n'avais besoin de décaler aucun des octets ;-) Mais, patchelf ressemble exactement à ce que je veux. En plus de ne pas pouvoir utiliser un chemin relatif, il peut également prendre en charge le LD_LIBRARY_PATH que j'utilise de sorte que je n'ai pas besoin d'un wrapper. Je vous attribuerai la réponse dès que j'aurai l'occasion de la tester.
données le
1
Ça marche! Cela me donnera un chemin décent pour mélanger les programmes new-libc avec les programmes old-libc sur ce serveur. Pour les futurs lecteurs, la commande était patchelf --set-interpreter $JAVA/lib/ld-linux.so.2 --set-rpath $JAVA/lib:$JAVA/lib/i386:$JAVA/lib/i386/jli $JAVA/bin/java, où $ JAVA est le répertoire du JRE, et où j'avais rassemblé toutes les bibliothèques dépendantes et les ai placées dans le lib/répertoire du JRE.
données le
@dataless et j'ai toujours besoin de LD_LIBRARY_PATH pour contourner ce libjvm.so, car libstdc ++. so.6: ne peut pas ouvrir le fichier d'objet partagé: aucun fichier ou répertoire [root @ 97245bbe7cc1 tensorflow-java] #
Amos
@Amos Cela fait un moment, mais pour mon cas, je n'ai plus besoin de LD_LIBRARY_PATH car la valeur par défaut vient du binaire java. Mais, notez la partie où j'ai dit que j'ai fait le tour et trouvé toutes les bibliothèques utilisées par java et les ai copiées dans le répertoire java lib. J'avais l'habitude ldd $JAVA/bin/javad'avoir le premier. Il y a aussi quelques libc dynamiques dont vous avez besoin comme libnss.so
données