12

I am trying to grant the java executable the right to open ports below 1024 on Linux. Here is the setup

  • /home/test/java contains the Oracle Server JRE 7.0.25
  • CentOS 6.4

Here is what getcap returns

[test@centos6 java]$ pwd
/home/test/java

[test@centos6 java]$ getcap bin/java
bin/java = cap_net_bind_service+ep

[test@centos6 java]$ getcap jre/bin/java
jre/bin/java = cap_net_bind_service+ep

Trying to execute java gives the following error.

[test@centos6 java]$ bin/java
bin/java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
[test@centos6 java]$ jre/bin/java
jre/bin/java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory

Is it possible to run Java 7_u25 when the binary has been given elevated privileges with setcap, if so how?

JDK-6919633 : Runtime does not support POSIX File Capabilities (A.K.A. Linux Capabilities) says that

Note: when using the setcap the libraries needed by the java launcher
should be present in /usr/lib or any other "trusted" location that the
runtime loader (rtld) uses to find shared libraries.

How do I make the shared libraries trusted?

0

2 Answers 2

15

Until you asked the question I never even heard of this facility in Unix (file capabilities). I found this link which looks to have the solution as to how to make ld.so trust your shared libraries:

excerpt from that post

When one is raising the privileges of an executable, the runtime loader (rtld), better know as ld.so will not link with libraries in untrusted paths. This is the way the ld.so(1) has been designed. If one needs to run such an executable, then you have to add that path to the trusted paths of ld.so, the following describes how to do so:

Fedora 11:
% uname -a
Linux localhost.localdomain 2.6.29.4-167.fc11.i686.PAE #1 SMP Wed May 27 17:28:22 EDT 2009 i686 i686 i386 GNU/Linux
% sudo setcap cap_net_raw+epi ./jdk1.7.0_04/bin/java
% ./jdk1.7.0_04/bin/java -version
./jdk1.7.0_04/bin/java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory

Its kaput, Ok we are on the same page now, to fix this, create a file such as > this, with the path to libjli.so

% cat /etc/ld.so.conf.d/java.conf
/home/someuser/jdk1.7.0_04/jre/lib/i386/jli

This will add the the pathname to the trusted user path, that ld.so will use, to build its runtime cache, verify if ld.so is seeing it by doing this, need to run it as root, and a reboot may be necessary.

% ldconfig | grep libjli
libjli.so -> libjli.so
.......

Now test java:

% ./jdk1.7.0_04/bin/java -version
java version "1.7.0_04-ea"
Java(TM) SE Runtime Environment (build 1.7.0_04-ea-b18)

and there you have it.....

References

3
  • 1
    This approach seems to be a system wide change, is there way to restrict the trust on a per user basis so that user foo and bar can have their own different versions of java with different version of libjli.so without running into conflict.
    – ams
    Aug 24, 2013 at 1:42
  • 1
    @ams: you are trusting a program to give the user a capability they usually don't have. This is important: you are trusting program code to not misuse (nor let others misuse) that capability. That is why you have to trust those libraries at a system-wide level.
    – ninjalj
    Oct 16, 2013 at 11:40
  • @ams You can use the privbind utility to be able to do that on per-process basis, not per-executable basis.
    – mighq
    Dec 12, 2014 at 20:52
1

Just to show the full process to enable Java listenign at port 80 (or any port below 1024):

  • For a JAVA_HOME:
    $> export JAVA_HOME=/usr/local/java/graalvm-ce-java8-20.2.0
    
  • You should enable the capability to the java binary:
    $> sudo /sbin/setcap 'cap_net_bind_service=ep' /usr/local/java/graalvm-ce-java8-20.2.0/bin/java
    
  • After that you will start to get some error when running java:
    $> java -version
    ./bin/java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
    
  • To fix that you should update ldconfig. Just create a java.conf file:
    $> cat /etc/ld.so.conf.d/java.conf 
    /usr/local/java/graalvm-ce-java8-20.2.0/lib/amd64/jli
    /usr/local/java/graalvm-ce-java8-20.2.0/jre/lib/amd64/jli
    
    $> java -version
    
  • Now java works:
    $> java -version
    openjdk version "1.8.0_262"
    ...
    

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .