Usare alternativamente libc con hack ld-linux.so; metodo più pulito?


13

Ho un sistema legacy con un glibc molto vecchio, che non possiamo aggiornare senza incorrere in una montagna di lavori di test / validazione.

Ho dovuto eseguire più volte nuovi programmi (come Java 1.7) su quel sistema. Ho optato per una soluzione chroot, in cui impacchettavo tutte le librerie necessarie ed eseguivo un servizio in chroot.

Il chroot è comunque molto limitante e preferirei provare a risolvere il problema con LD_LIBRARY_PATH. Sfortunatamente, ricevo un errore libc.so.6: cannot handle TLS dataquando lo provo.

Si scopre che ho bisogno anche /lib/ld-linux.so.2del chroot. Questo funziona:

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

Tuttavia, javaostacola il mio trucco ispezionando /proc/self/cmdlineper determinare da dove caricare le sue librerie, il che non riesce se il binario non è stato chiamato 'bin / java'. Anche java si esegue automaticamente all'avvio, complicando ulteriormente le cose.

In un ultimo tentativo di far funzionare questo, ho aperto il binario java con un editor esadecimale e ho sostituito la stringa /lib/ld-linux.so.2con /home/chroot/ld.so(e ho creato un link simbolico a ld-linux.so.2), e ha funzionato!

Ma penso che tutti sarebbero d'accordo sul fatto che è un grosso kludge riscrivere il percorso di ogni nuovo binario in un percorso assoluto del sistema nidificato.

Qualcuno conosce un modo più pulito di utilizzare un percorso di libreria personalizzato incluso un ld-linux.so personalizzato?

Risposte:


12

Il percorso del caricatore viene compilato nel file binario come hai scoperto con il tuo editor esadecimale. In realtà sei stato fortunato che la modifica del binario ha funzionato direttamente perché entrambi /lib/ld-linux.so.2e /home/chroot/ld.sohanno la stessa lunghezza. Le lunghezze di quelle stringhe sono anche nel file binario e puoi causare problemi sottili se modifichi direttamente le stringhe.

Se finisci per seguire il percorso dovresti dare un'occhiata a qualcosa come patchelf per aggiornare l'interprete. Ciò ti consentirebbe di cambiare in modo permanente l'interprete in modo rapido e sicuro.


Non è stata fortuna, sapevo che non avevo bisogno di spostare nessuno dei byte ;-) Ma il patchelf sembra proprio quello che voglio. Oltre a non poter utilizzare un percorso relativo, può anche occuparsi del LD_LIBRARY_PATH che sto usando in modo da non aver bisogno di un wrapper. Ti darò credito per la risposta non appena avrò la possibilità di testarla.
dataless

1
Funziona! Questo mi darà un percorso decente per mescolare i programmi new-libc con i programmi old-libc su questo server. Per i futuri lettori, il comando era patchelf --set-interpreter $JAVA/lib/ld-linux.so.2 --set-rpath $JAVA/lib:$JAVA/lib/i386:$JAVA/lib/i386/jli $JAVA/bin/java, dove $ JAVA è la directory di JRE e dove avevo arrotondato tutte le librerie dipendenti e le avevo inserite nella lib/directory di JRE.
dataless

@dataless bene ho ancora bisogno di LD_LIBRARY_PATH per aggirare questo libjvm.so, perché libstdc ++. so.6: impossibile aprire il file oggetto condiviso: nessun file o directory [root @ 97245bbe7cc1 tensorflow-java] #
Amos

@Amos È passato un po 'di tempo, ma per il mio caso non avevo più bisogno di LD_LIBRARY_PATH perché l'impostazione predefinita proviene dal binario java. Tuttavia, nota la parte in cui ho detto che sono andato in giro e ho trovato tutte le librerie utilizzate da Java e le ho copiate nella directory lib di Java. Ero solito ldd $JAVA/bin/javaottenere l'ist. Ci sono anche alcuni libc dinamici di cui hai bisogno come libnss.so
dataless
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.