8

I am scripting the creation of chroot jails and part of that automation includes copying various executables and their dependencies into the jail. I am using the following bash line to parse the file paths out of a list of dependencies (for java, for instance):

$ ldd `which java` | grep -o '/[^()]*'
/lib/x86_64-linux-gnu/libz.so.1
/lib/x86_64-linux-gnu/libpthread.so.0
/lib/x86_64-linux-gnu/libdl.so.2
/lib/x86_64-linux-gnu/libc.so.6
/lib64/ld-linux-x86-64.so.2

This works great for Node.js and Python, but when I try to execute java from within the jail, I get an error:

java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory

It turns out that the libjli.so path is missing from the list of dependencies... at least those that ldd shows us (line 5):

$ ldd `which java`
linux-vdso.so.1 =>  (0x00007ffff7f4d000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f7ac3928000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f7ac370c000)
libjli.so => not found
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f7ac3507000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7ac317c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7ac3b48000)

I found the file...

$ find /usr/lib -name libjli.so
/usr/lib/jvm/java-6-openjdk-amd64/lib/amd64/jli/libjli.so
/usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/jli/libjli.so

... but I would like to know why it wasn't listed with ldd. It is a known dependency apparently, but the path is unknown? Any help is appreciated!

Michael Mrozek
  • 91,316
  • 38
  • 238
  • 232
Rip Leeb
  • 347
  • 2
  • 4
  • 9
  • Interesting question, You could try asking this on an openjdk forum. – Faheem Mitha Nov 06 '14 at 01:38
  • In case someone stumbles on this from google: it seems like it may be a duplicate with http://unix.stackexchange.com/questions/16656, which has more information (and different answers). – yshavit Feb 06 '15 at 17:53

2 Answers2

7

It's supposed to work out of the box - with no messing with /etc/ld.so.conf* or ldconfig - and it can easily do so. Just mount /proc in your chroot. I do this with the following line in /etc/fstab in my real-root fs:

/proc /var/chroot/ia32/proc none bind

Thus binding it to the real /proc.

Per https://github.com/cedric-vincent/PRoot/issues/9, ld-linux.so (I guess it is) determines $ORIGIN for substituting into the objdump -p's RPATH entries by looking at /proc/self/exe.

How many times have I been bitten by this and had to rediscover it? Please, oh mighty and wise Google, lead me back here expeditiously next time, so future-me can learn again at the knee of past-me!

Martin Dorey
  • 214
  • 2
  • 8
  • 1
    Thanks. Your pointing at `/proc/self/exe` was the missing clue at my side. Mounting `/proc` in my chroot did the trick. – Tino Dec 04 '15 at 15:05
3

It seems that you need to add

/usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/jli

to /etc/ld.so.conf, or more likely to a new file in /etc/ld.so.conf.d. Then run ldconfig to update the cache so ldd will find the library.

For scripting chroots, you'll probably have less pain in the long run to take a package-based approach, creating a base install first (using e.g. debootstrap on Debian-based hosts), then installing the packages you want. That lets the package manager take care of all of the work of resolving dependencies, installing all of the needed files, and running postinstall tasks.

  • And can you tell me why it wasn't in ld.so.conf or one of the included files? Should the OS have put it there during install? – Rip Leeb Oct 30 '14 at 16:23
  • No, I don't know that. I can say that I see the same result on my Ubuntu 14.04 host, and yet java starts fine. So it must be resolving the dependency dynamically at run time. – Andrew Schulman Oct 30 '14 at 17:01