Trying to execute my Java app yields a UnsatisfiedLinkError
exception when the libmysqlclient.so.18 can not be found, even when it is explicitly declared in LD_LIBRARY_PATH, -Djava.library.path and /etc/ld.so.conf
I am trying to make use of pcap4j (https://github.com/kaitoy/pcap4j), a Java wrapper for libpcap, so I can sniff packets on my machine NIFs from a Java application. As libpcap requires superuser privileges to perform this task, I have to somehow give the non-privileged user executing this app the capacity of accessing the NIFs.
The maintainer of pcap4j suggests granting capabilities CAP_NET_RAW
and CAP_NET_ADMIN
to the java command as follow:
setcap cap_net_raw,cap_net_admin=eip /path/to/java
Due to implementation limitations I am constrained as follow:
After granting CAP_NET_RAW
and CAP_NET_ADMIN
capabilites to the java command, the problem arose. I am getting the following exception when executing my app:
Error creating entity
java.lang.UnsatisfiedLinkError: /path/to/app/lib/libxpherejava.so: libmysqlclient.so.18: cannot open shared object file: No such file or directory
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
JAVA: java-1.8.0-openjdk-1.8.0.171-8
OS: Linux user-me 3.10.0-862.6.3.el7.x86_64 #1 SMP Fri Jun 15 17:57:37 EDT 2018 x86_64 x86_64 x86_64 GNU/Linux [Red Hat Enterprise Linux Server release 7.5 (Maipo)]
LD_LIBRARY_PATH contains an explicit path to the not found library:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/lwp:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.171-8.b10.el7_5.x86_64/jre/lib/amd64/jli/libjli.so:/usr/lib64/mysql/libmysqlclient.so.18
export LD_LIBRARY_PATH
LD_LIBRARY_PATH is passed to the JVM by making use of java.library.path:
exec java
-XshowSettings:properties
-Djava.library.path=${LD_LIBRARY_PATH}
-d64
...
The "-XshowSettings:properties" provides me with the following output when the java command is executed:
java.library.path =
/path/to/app/lib
/path/to/app/lib/glib-2.0
/usr/lib/lwp
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.171-8.b10.el7_5.x86_64/jre/lib/amd64/jli/libjli.so
/usr/lib64/mysql/libmysqlclient.so.18
where /usr/lib64/mysql/libmysqlclient.so.18
is a symlink to /usr/lib64/mysql/libmysqlclient.so.18.0.0
Seems like JVM (or whatever entity is requesting access to libmysqlclient.so.18 from libxpherejava.so) does not find libmysqlclient.so.18, even when its path is explicitly provided to the java.library.path and the file DOES exist.
With LD_LIBRARY_PATH containing the path to libmysqlclient.so.18 (/usr/lib64/mysql/libmysqlclient.so.18), issuing ldd of libxpherejava.so yields that libmysqlclient.so.18 can not be found
[user@user-me log]$ ldd /path/to/app/lib/libxpherejava.so
linux-vdso.so.1 => (0x00007ffe1a73d000)
libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007fd727df4000)
libssl.so.10 => /lib64/libssl.so.10 (0x00007fd727b83000)
libxphereS.so => /path/to/app/lib/libxphereS.so (0x00007fd727973000)
libmysqlclient.so.18 => not found
libz.so.1 => /lib64/libz.so.1 (0x00007fd72775d000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007fd727543000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fd727327000)
libm.so.6 => /lib64/libm.so.6 (0x00007fd727025000)
libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x00007fd726d11000)
libc.so.6 => /lib64/libc.so.6 (0x00007fd726944000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fd726740000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007fd7264f3000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007fd72620b000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007fd726007000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007fd725dd4000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd728718000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fd725b72000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007fd725964000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007fd725760000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fd725547000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fd725320000)
This is the content of ld.so.conf:
[user@user-me lib]$ cat /etc/ld.so.conf
/path/to/app/lib/
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.171-8.b10.el7_5.x86_64/jre/lib/amd64/jli/libjli.so
/usr/lib64/mysql/libmysqlclient.so.18
Both libs are 64-bit compiled:
[user@user-me lib]$ file libxpherejava.so
libxpherejava.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=82e1c673e732eb2d3770883b14facf3eff091243, not stripped
[user@user-me lib]$ file /usr/lib64/mysql/libmysqlclient.so.18
/usr/lib64/mysql/libmysqlclient.so.18: symbolic link to libmysqlclient.so.18.0.0'
[user@user-me lib]$ file /usr/lib64/mysql/libmysqlclient.so.18.0.0
/usr/lib64/mysql/libmysqlclient.so.18.0.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=79978c5f4fb259a5a146614e260ea0720dd31d3b, stripped
A strace over the script that executes the "exec java" command yields this --> https://dumpz.org/aGHQpNk9Znmk
Does anyone know why is libmysqlclient.so.18 not being found?
Creating a symlink to the problematic library libmysqlclient.so.18
under /usr/lib64
solves the problem. The exception is gone.