Usando libc alternativo com ld-linux.so hacks; método mais limpo?

13

Eu tenho um sistema legado com um glibc muito antigo, que não podemos atualizar sem incorrer em uma montanha de trabalho de teste / validação.

Eu precisava executar programas mais recentes (como o Java 1.7) nesse sistema várias vezes agora. Optei por uma solução chroot, onde empacote todas as bibliotecas necessárias e execute um serviço em um chroot.

O chroot é muito limitador, e eu prefiro tentar resolver o problema com LD_LIBRARY_PATH. Infelizmente, recebo um erro libc.so.6: cannot handle TLS dataquando tento isso.

Acontece que eu preciso /lib/ld-linux.so.2do chroot também. Isso funciona:

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

No entanto, javafrustra meu truque inspecionando /proc/self/cmdlinepara determinar de onde carregar suas bibliotecas, o que falha se o binário não tiver sido chamado de 'bin / java'. Também o java se executa durante a inicialização, complicando ainda mais as coisas.

Em uma última tentativa de fazer isso funcionar, abri o binário java com um editor hexadecimal e substituí a string /lib/ld-linux.so.2por /home/chroot/ld.so(e fiz disso um link simbólico ld-linux.so.2), e funcionou!

Mas eu acho que todos concordariam que é um enorme erro reescrever o caminho de todo novo binário para um caminho absoluto do sistema aninhado.

Alguém conhece uma maneira mais limpa de usar um caminho de biblioteca personalizado, incluindo um ld-linux.so personalizado?

sem data
fonte

Respostas:

12

O caminho para o carregador é compilado no binário como você descobriu com seu editor hexadecimal. Você realmente teve sorte que editar o binário funcionou diretamente porque ambos /lib/ld-linux.so.2e /home/chroot/ld.sotêm o mesmo comprimento. Os comprimentos dessas strings também estão no binário e você pode causar problemas sutis se modificar as strings diretamente.

Se você acabar seguindo o caminho, consulte algo como o patchelf para atualizar o intérprete. Isso permitiria que você alterasse permanentemente o intérprete com rapidez e segurança.

gmjosack
fonte
Não foi sorte, eu sabia que precisava não mudar nenhum dos bytes ;-) Mas, patchelf parece exatamente o que eu quero. Além de não poder usar um caminho relativo, ele também pode cuidar do LD_LIBRARY_PATH que estou usando para não precisar de um wrapper. Dou crédito pela resposta assim que tiver a chance de testá-la.
dataless
1
Funciona! Isso me dará um caminho decente a seguir para misturar programas new-libc com os programas old-libc neste servidor. Para futuros leitores, o comando foi patchelf --set-interpreter $JAVA/lib/ld-linux.so.2 --set-rpath $JAVA/lib:$JAVA/lib/i386:$JAVA/lib/i386/jli $JAVA/bin/javaonde $ JAVA é o diretório do JRE e onde reuni todas as bibliotecas dependentes e as coloquei no lib/diretório do JRE.
dataless
@dataless bem, eu ainda preciso do LD_LIBRARY_PATH para solucionar esse libjvm.so, porque o libstdc ++. so.6: não é possível abrir o arquivo de objeto compartilhado: nenhum arquivo ou diretório desse tipo [root @ 97245bbe7cc1 tensorflow-java] #
Amos
@Amos Já faz um tempo, mas para o meu caso eu não precisava mais do LD_LIBRARY_PATH porque o padrão vem do binário java. Mas observe a parte em que eu disse que procurei todas as bibliotecas usadas pelo java e as copiei no diretório java lib. Eu costumava ldd $JAVA/bin/javapegar o ist. Há também alguns dinâmica libc que você precisa, como libnss.so
sem dados