Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Exploiter facilement des fonctions natives avec...

Exploiter facilement des fonctions natives avec le projet panama

Courte introduction du tools-in-action au Devoxx France 2022 sur l'appel de fonctions natives sur le JDK18 et la JEP-419.
Code: https://github.com/bric3/panama-watch

Brice Dutheil

April 21, 2022
Tweet

More Decks by Brice Dutheil

Other Decks in Technology

Transcript

  1. Agenda 1. Le projet panama, c’est quoi ? 2. Demo

    JEP-419 3. Demo de jextract 4. Question
  2. We had alternatives package q.r.s; class NativeBinding { static {

    System.load("{path/to/libNative.so} "); } public static native boolean isatty( int fileDescriptor ); } #include "q_r_s_Native.h" #include <unistd.h> JNIEXPORT jboolean JNICALL Java_q_r_s_NativeBinding_isatty( JNIEnv *env, jclass cls, jint fileDescriptor ) { return isatty(fileDescriptor)? JNI_TRUE: JNI_FALSE; } $ javac -d classes -cp src \ -h jni q/r/s/Native.java $ gcc \ -I $JAVA_HOME/include \ -I $JAVA_HOME/include/linux \ -fPIC \ -shared \ -o Native.so \ Native.c JNI 🏎 Efficient 🏗 Complex Build ☣ Can terminate the JVM
  3. We had alternatives package q.r.s; class NativeBinding { static {

    System.load("{path/to/libNative.so} "); } public static native boolean isatty( int fileDescriptor ); } #include "q_r_s_Native.h" #include <unistd.h> JNIEXPORT jboolean JNICALL Java_q_r_s_NativeBinding_isatty( JNIEnv *env, jclass cls, jint fileDescriptor ) { return isatty(fileDescriptor)? JNI_TRUE: JNI_FALSE; } $ javac -d classes -cp src \ -h jni q/r/s/Native.java $ gcc \ -I $JAVA_HOME/include \ -I $JAVA_HOME/include/linux \ -fPIC \ -shared \ -o Native.so \ Native.c JNI JNA public interface JNA_Library extends Library { JNA_Library INSTANCE = (JNA_Library) Native.loadLibrary( "c", JNA_Library.class ); boolean isatty(int fileDescriptor); } 📦 Third party 🎚 Easy to use 🚜 Versatile, not fast
  4. We had alternatives package q.r.s; class NativeBinding { static {

    System.load("{path/to/libNative.so} "); } public static native boolean isatty( int fileDescriptor ); } #include "q_r_s_Native.h" #include <unistd.h> JNIEXPORT jboolean JNICALL Java_q_r_s_NativeBinding_isatty( JNIEnv *env, jclass cls, jint fileDescriptor ) { return isatty(fileDescriptor)? JNI_TRUE: JNI_FALSE; } $ javac -d classes -cp src \ -h jni q/r/s/Native.java $ gcc \ -I $JAVA_HOME/include \ -I $JAVA_HOME/include/linux \ -fPIC \ -shared \ -o Native.so \ Native.c JNI JNA public interface JNA_Library extends Library { JNA_Library INSTANCE = (JNA_Library) Native.loadLibrary( "c", JNA_Library.class ); boolean isatty(int fileDescriptor); } JNR-FFI public interface IsATTY_JNRFFI { boolean isatty(int fileDescriptor); } import jnr.ffi.LibraryLoader; IsATTY_JNRFFI c = LibraryLoader.create(IsATTY_JNRFFI.class) .load("c"); 📦 Third party 🎚 Easy to use 🏎 Almost as fast as JNI
  5. Support from the runtime Objective: • easy support of foreign

    function without 3rd party • efficient • flexible • improved security • rely on MethodHandles
  6. • JEP-191 • 14 ⇒ JEP-370 • 15 ⇒ JEP-383

    • 16 ⇒ JEP-338, JEP-389, JEP-393 • 17 ⇒ JEP-412, JEP-414 • 18 ⇒ JEP-417 Vector API (3nd Incubator) JEP-419 Foreign Function & Memory API (2nd Incubator) • 19 ⇒ JEP-424 Foreign Function & Memory API(Preview)
  7. Invoke native code with JDK 18 Project is still incubating,

    so it requires to add modules • for compilation • and for execution $ javac --add-modules jdk.incubator.foreign ... $ java --enable-native-access=ALL-UNNAMED \ --add-modules jdk.incubator.foreign ...
  8. Invoke native code with JDK 18 var lookup = CLinker.systemCLinker();

    System.load(libPath.toAbsolutePath().toString()); var lookup = SymbolLookup.loaderLookup(); Choose the right lookup • systemLookup for system symbols like those in libc • loaderLookup for loaded libraries
  9. Invoke native code with JDK 18 MethodHandle crypto_box_keypair = CLinker.systemCLinker().downcallHandle(

    lookup.lookup("crypto_box_keypair").get(), FunctionDescriptor.ofVoid(ADDRESS, ADDRESS) ); Create the method handle
  10. Invoke native code with JDK 18 try (var scope =

    ResourceScope.newConfinedScope()) { var segmentAllocator = SegmentAllocator.nativeAllocator(scope); var recipientPublicKey = segmentAllocator.allocate(crypto_box_publickeybytes()); var recipientSecretKey = segmentAllocator.allocate(crypto_box_secretkeybytes()); crypto_box_keypair.invoke(recipientPublicKey.address(), recipientSecretKey.address()); } Open a scope (for memory safety) ⚠ newImplicitScope ⟹ closed by GC 👌 newConfinedScope ⟹ full control
  11. Invoke native code with JDK 18 try (var scope =

    ResourceScope.newConfinedScope()) { var segmentAllocator = SegmentAllocator.nativeAllocator(scope); var recipientPublicKey = segmentAllocator.allocate(crypto_box_publickeybytes()); var recipientSecretKey = segmentAllocator.allocate(crypto_box_secretkeybytes()); crypto_box_keypair.invoke(recipientPublicKey.address(), recipientSecretKey.address()); } Allocate memory within that scope
  12. Invoke native code with JDK 18 try (var scope =

    ResourceScope.newConfinedScope()) { var segmentAllocator = SegmentAllocator.nativeAllocator(scope); var recipientPublicKey = segmentAllocator.allocate(crypto_box_publickeybytes()); var recipientSecretKey = segmentAllocator.allocate(crypto_box_secretkeybytes()); crypto_box_keypair.invoke(recipientPublicKey.address(), recipientSecretKey.address()); } Make the call
  13. Better memory mapped files Memory mapping files in memory is

    a OS feature Allows to put the region of a file in memory MappedByteBuffer implements this feature • ⚠ stays in memory until the buffer itself is garbage collected
  14. Replacing MappedByteBuffer try (var fileChannel = FileChannel.open(src, StandardOpenOption.READ)) { var

    mappedByteBuffer = fileChannel.map( FileChannel.MapMode.READ_ONLY, 0, fileChannel.size()); } FileChannel.map create the memory mapped region
  15. Replacing MappedByteBuffer try (var scope = ResourceScope.newConfinedScope()) { var mappedFile

    = MemorySegment.mapFile( src, 0, Files.size(src), FileChannel.MapMode.READ_ONLY, scope); } Map the file in memory
  16. Le projet Panama ? • JEP 419 (Java 18) https://openjdk.java.net/jeps/419

    • A practical look at JEP 412 (Java 17) with Libsodium https://blog.arkey.fr/2021/09/04/a-practical-look-at-jep-412-in-j dk17-with-libsodium/ • Java Project Panama au ParisJug Nov 2021 (deep dive de 1h30) https://youtu.be/hrqi-KJ_74I • https://inside.java • https://github.com/bric3/panama-watch