Usando libc alternativo con ld-linux.so hacks; método más limpio?

13

Tengo un sistema heredado con un glibc muy antiguo, que no podemos actualizar sin incurrir en una montaña de trabajo de prueba / validación.

He necesitado ejecutar programas más nuevos (como Java 1.7) en ese sistema varias veces ahora. Opté por una solución chroot, donde empaqueto todas las bibliotecas necesarias y ejecuto un servicio en un chroot.

Sin embargo, el chroot es muy limitante, y prefiero tratar de resolver el problema con LD_LIBRARY_PATH. Desafortunadamente, recibo un error libc.so.6: cannot handle TLS datacuando intento eso.

Resulta que también necesito /lib/ld-linux.so.2el chroot. Esto funciona:

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

Sin embargo, javafrustra mi truco al inspeccionar /proc/self/cmdlinepara determinar dónde cargar sus bibliotecas, lo que falla si el binario no se llamaba 'bin / java'. También Java se ejecuta durante el inicio, lo que complica aún más las cosas.

En un último intento para hacer que esto funcione, abrí el binario java con un editor hexadecimal y reemplacé la cadena /lib/ld-linux.so.2con /home/chroot/ld.so(y lo convertí en un enlace simbólico ld-linux.so.2), ¡y funcionó!

Pero creo que todos estarían de acuerdo en que es un error enorme reescribir la ruta de cada nuevo binario a una ruta absoluta del sistema anidado.

¿Alguien conoce una forma más limpia de usar una ruta de biblioteca personalizada que incluya un ld-linux.so personalizado?

sin datos
fuente

Respuestas:

12

La ruta al cargador se compila en el binario como descubrió con su editor hexadecimal. Que en realidad nos la suerte de que la edición de la binaria directa funcionó porque tanto /lib/ld-linux.so.2y /home/chroot/ld.sotienen la misma longitud. Las longitudes de esas cadenas también están en el binario y puede causar problemas sutiles si modifica las cadenas directamente.

Si termina yendo por la ruta, debería echar un vistazo a algo como parchelf para actualizar el intérprete. Esto le permitiría cambiar permanentemente el intérprete de forma rápida y segura.

gmjosack
fuente
No fue suerte, sabía que no necesitaba cambiar ninguno de los bytes ;-) Pero, patchelf se parece a lo que quiero. Además de no poder usar una ruta relativa, también puede encargarse de LD_LIBRARY_PATH que estoy usando para que no necesite un contenedor. Le daré crédito por la respuesta tan pronto como tenga la oportunidad de probarla.
datos el
1
¡Funciona! Esto me dará un camino decente para mezclar programas new-libc con los programas old-libc en este servidor. Para futuros lectores, el 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, donde $ JAVA es el directorio del JRE, y donde había redondeado todas las bibliotecas dependientes y las había colocado en el lib/directorio del JRE.
datos
@dataless bueno, todavía necesito LD_LIBRARY_PATH para solucionar este libjvm.so, porque libstdc ++. so.6: no se puede abrir el archivo de objeto compartido: No existe tal archivo o directorio [root @ 97245bbe7cc1 tensorflow-java] #
Amos
@Amos Ha pasado un tiempo, pero para mi caso ya no necesitaba LD_LIBRARY_PATH porque el valor predeterminado proviene del binario java. Pero, tenga en cuenta la parte en la que dije que di la vuelta y encontré todas las bibliotecas utilizadas por Java y las copié en el directorio de la biblioteca Java. Solía ldd $JAVA/bin/javaobtener el ist. También hay algunos libc dinámicos que necesita, como libnss.so
datos del