Debian – Problem to launch java at Debian: “error while loading shared libraries: libjli.so”

debiandynamic-linkingjavapermissions

I'm trying to launch java:

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

$ ldd /usr/lib/jvm/java-6-openjdk/jre/bin/java
        linux-gate.so.1 =>  (0xb779f000)
        libz.so.1 => /usr/lib/libz.so.1 (0xb7780000)
        libpthread.so.0 => /lib/i686/cmov/libpthread.so.0 (0xb7767000)
        libjli.so => /usr/lib/jvm/java-6-openjdk/jre/bin/../lib/i386/jli/libjli.so (0xb7762000)
        libdl.so.2 => /lib/i686/cmov/libdl.so.2 (0xb775e000)
        libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7603000)
        /lib/ld-linux.so.2 (0xb77a0000
$ ls /usr/lib/jvm/java-6-openjdk/jre/bin/../lib/i386/jli/
libjli.so

But java works under root:

$ sudo java -version
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8.7) (6b18-1.8.7-2~lenny1)
OpenJDK Client VM (build 14.0-b16, mixed mode, sharing)

UPD:

/usr/lib/jvm/java-6-openjdk/jre/bin/java is actually my java command:

$ type java
java is hashed (/usr/bin/java)
$ ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22 Jul 14 10:15 /usr/bin/java -> /etc/alternatives/java
$ ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 40 Jul 14 10:36 /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java

UPD2:

I've also tried to set root PATH:

$ sudo su
# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# exit
$ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ java -version
java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory

UPD3:

I'm tried:

# comm -3 <(declare | sort) <(declare -f | sort)

under root. But there is no usable environment variables for java.

UPD4:

strace -f java -version result: http://dumpz.org/67368/

Best Answer

open("$ORIGIN/../lib/i386/jli/tls/i686/sse2/cmov/libz.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)

The executable you're running looks for libraries in an rpath in addition to the normal library search path. The rpath here is $ORIGIN/../lib/i386/jli:$ORIGIN/../jre/lib/i386/jli. Normally $ORIGIN should be replaced by the location of the executable, here /usr/lib/jvm/java-6-openjdk/jre/bin.

Here, $ORIGIN isn't being replaced. The feature is turned off in executables running with extra privileges (setuid, setgid, or setpcap), because otherwise you might be able to inject a different library and so run arbitrary code with elevated privileges. (See this article for a more detailed explanation.) The security issue was discovered relatively recently; in Debian it was fixed in DSA-2122-1, so before you upgraded to libc6-2.7-18lenny6, your java executable would presumably have worked.

The symptom indicates that java is running with additional privileges. This is not the case in a normal Debian installation. Make sure that /usr/lib/jvm/java-6-openjdk/jre/bin/java is mode 755 and doesn't have any capabilities (getcap /usr/lib/jvm/java-6-openjdk/jre/bin/java, and setcap -r … to remove the capabilities if any).


(Original answer, which may be useful if you find that java works as root but not as other users, and it does turn out that you're invoking different binaries.)

My bet is that you have some other java version earlier on your PATH (sudo changes the PATH). Check what type java says — it's probably some different Java version for which ldd /path/to/bin/java reports libjli.so => not found.

And I speculate that the reason that this Java version can't find libjli.so is that it's looking for it through a rpath (library search path stored in the executable) that doesn't match the way it's installed. If you have the java binary in /some/where/bin/java, and it has a relative rpath (which is the way of the Sun JDK and OpenJDK), the library should be in /some/where/lib/i386/jli/libjli.so (assuming an i386 architecture). If the rpath is absolute, you need to either put libjli.so in the exact specified location, or set LD_LIBRARY_PATH to include where libjli.so is.

Related Question