Search code examples
rheljavashared-libraries

UnsatisfiedLinkError exception when lib is explicitly declared


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

PROBLEM DESCRIPTION

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:

  • Avoid giving sudo access to the non-privileged user due to security policies. The same reasoning could be applied to granting above mentioned capabilities to the java command (do not know if capability grantings are given per user/command pair), but, from my relatively scarce knowledge about security, the latter option looks like a more delimited permission granting method for what I want to achieve (solutions are welcome too should an alternative permission granting method looks more suitable for my purpose), and given that the pcapj4 developer, a likely more experienced professional, advices so, I have followed the capability granting path.
  • User must be able to execute the app without being password-prompted
  • Permission granting must be done only once, e.g. when creating the user for the first time.

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)

DETAILS

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

RELATED QUESTIONS

Does anyone know why is libmysqlclient.so.18 not being found?


Solution

  • Creating a symlink to the problematic library libmysqlclient.so.18 under /usr/lib64 solves the problem. The exception is gone.