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.hfile with the command
javac -h . SocketTester.java
- Create
socketTester.cfile that implementssocketTester.hand which needs thecap_net_rawcapabitily - 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.soto /usr/lib - Run
sudo ldconfig
- Set the cap
cd /usr/lib
sudo setcap cap_net_raw=epi libSocketTester.so
- Create a
Test.javaclass
public static void main(final String[] args) {
SocketTester tester = new SocketTester();
tester.socketTest();
}
- Create a jar with
SocketTester.javaandTest.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?