Context
I've done a java library that uses a C library with JNI.
The C library is compiled in linux into a .so
file. This library needs cap_net_raw
capabilities.
Goal
Execute a java process without additional privileges, that uses said java library. The actual processes that are going to use the library are existing processes already in prod and we don't want to give them more rights.
To test that, I've created a jar
and run it both with and without sudo
. As expected, it succeeds with but fail without it.
Steps to reproduce the test
- Create a java class with a native method, let's call it
SocketTester.java
static {
System.loadLibrary("SocketTester");
}
private native int socketTest();
- Generate
socketTester.h
file with the command
javac -h . SocketTester.java
- Create
socketTester.c
file that implementssocketTester.h
and which needs thecap_net_raw
capabitily - Compile with
gcc -o libSocketTester.so socketTester.c -shared -I/usr/lib/jvm/java-14-openjdk-amd64/include -I/usr/lib/jvm/java-14-openjdk-amd64/include/linux
- Move
libSocketTester.so
to /usr/lib - Run
sudo ldconfig
- Set the cap
cd /usr/lib
sudo setcap cap_net_raw=epi libSocketTester.so
- Create a
Test.java
class
public static void main(final String[] args) {
SocketTester tester = new SocketTester();
tester.socketTest();
}
- Create a jar with
SocketTester.java
andTest.java
- Run the test
java -cp socketTester.jar Test
What I've already tried
Adding cap to the .so
lib
sudo setcap cap_net_raw=epi libSocketTester.so
Result: Failure
Adding cap to java
sudo setcap cap_net_raw=epi /usr/lib/jvm/java-14-openjdk-amd64/bin/java
Result: It works, but it's not what I want because now all java process have the capability (see bold in goal section).
The question
Why is adding the cap to the .so
doesn't work? How else can I accomplish the goal?
man capabilities
, it seems capabilities can be set on an executable file. You could try to build a JNI library calling an executable file with the capability needed.File capabilities > Since kernel 2.6.24, the kernel supports associating capability sets with an executable file using setcap(8).
– Mikisojava.lang.Runtime#exec()
– Mikiso