'JNI: SIGSEGV when calling native function from Java, after native registration of same function on library second opening

I have an Android app that is structured in the following way:

  • CORE: Is the class of the accessibility service that dinamically loads a few dex files. It will be loaded when app starts;
  • MODULE: Is the classe created by loading relative dex file

Actions

  1. When Core starts, in onServiceConnected, this service loads a native library libbridge.so.
  • libbridge.so exposes two methods:
    • openLib(module):
      • this method opens the library libcloser.so first time and libcloser_2.so second time. These two libs are equals, only names are different.
      • registers a function called doSum of libcloser.so / libsloser_2.so by using RegisterNatives JNI function, to the module received in input.
         void* func = dlsym(handle, "Java_com_android_dynamic_FileGrabberModule_doSum");
         static JNINativeMethod methods[] = { {"doSum", "()V", func} };
         jclass clazz = env->GetObjectClass(module);
         int ret = (*env).RegisterNatives(clazz, methods, sizeof(methods)/sizeof(methods[0]));
         if (ret == 0) {
             LOGI("registerNatives() Successfull registration");
         } else {
             LOGI("registerNatives() Registration Failed");
         }
         (*env).DeleteLocalRef( clazz );
        
    • closeLib(module): Unregisters the function doSum for the module received in input and closes the libcloser.so / libsloser_2.so lib
      jclass clazz = env->GetObjectClass(module);
      int ret = (*env).UnregisterNatives(clazz);
      if (ret == 0) {
          LOGI("unregisterNatives() Successfull unregistration");
      } else {
          LOGI("unregisterNatives() Unregistration Failed");
      }
      (*env).DeleteLocalRef( clazz );
      
  1. Core exposes two methods:

    • onOpenLib(module): Calls libbridge.so method openLib(module)
    • onCloseLib(module): Calls libbridge.so method closeLib(module)
  2. From the Module, dinamically loaded from a dex, in doSumInLib function (called from constructor), Core openLib(module) is called, passing this: Core.onOpenLib(this)

    • libbridge.so openLib(module) is called;
    • libcloser.so is opened, and an handle is returned;
    • the function doSum is registered (with the same handle);
  3. When Module call function doSum(), libcloser.so is called and executes code successfully.

  4. With certain conditions, Core terminates the Module thread.

    • Core onCloseLib(module) is called;
    • libbridge.so closeLib(module) is called;
    • function are unregistered (with the same handle);
    • libcloser.so is closed (by the same handle);
  5. After some time, Core reloads the Module from the dex file and tries to execute the same actions writed before (Back to 3). Now the lib that will be opened is libcloser_2.so.

At this time, when point 3 is executed again, when Module call libcloser_2.so doSum(), JNI crash and return this stack:

Build fingerprint: 'xiaomi/jasmine/jasmine_sprout:9/PKQ1.180904.001/V10.0.17.0.PDIMIXM:user/release-keys'
DEBUG   : Revision: '0'
DEBUG   : ABI: 'arm64'
DEBUG   : pid: 17433, tid: 17517, name: Thread-3  >>> com.xxxxx.xxxx <<<
DEBUG   : signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x72f74536b8
DEBUG   :     x0  000000730d82fc40  x1  00000072f92f58f4  x2  005b0000fc9280a0  x3  ac6603ef4e6e40fd
DEBUG   :     x4  0000000000000000  x5  0000000000000002  x6  00000072fc9280a0  x7  ac6603ef4e6e40fd
DEBUG   :     x8  ac6603ef4e6e40fd  x9  ac6603ef4e6e40fd  x10 0000000000430000  x11 00000072f92f5860
DEBUG   :     x12 00000072f92f58f4  x13 00000072f92f58e8  x14 0000000000000000  x15 00000072f92f43b8
DEBUG   :     x16 00000072f74536b8  x17 0000000000000000  x18 0000000000000010  x19 00000072fc928000
DEBUG   :     x20 0000000000000000  x21 00000072fc928000  x22 00000072f92f5bc0  x23 00000072f653e33b
DEBUG   :     x24 0000000000000004  x25 00000072f92f9588  x26 00000072fc9280a0  x27 0000000000000001
DEBUG   :     x28 00000072f92f58f0  x29 00000072f92f58f0
DEBUG   :     sp  00000072f92f58d0  lr  00000073162befe4  pc  00000072f74536b8
linker  : CANNOT LINK EXECUTABLE "/system/bin/dpmd": "/system/lib64/libdpmframework.so" is 32-bit instead of 64-bit
[Wed Sep 01 11:08:57 GMT+02:00 2021] : [Downloader_88cfcebe-c617-4e72-b27f-5676229afb61] Received heartbeat ack
DEBUG   :
DEBUG   : backtrace:
DEBUG   :     #00 pc 00000000000eb6b8  <anonymous:00000072f7368000>
DEBUG   :     #01 pc 000000000055dfe0  /system/lib64/libart.so (offset 0x43f000) (art_quick_generic_jni_trampoline+144)
DEBUG   :     #02 pc 0000000000554f88  /system/lib64/libart.so (offset 0x43f000) (art_quick_invoke_stub+584)
DEBUG   :     #03 pc 00000000000cf6c8  /system/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+200)
DEBUG   :     #04 pc 000000000027f230  /system/lib64/libart.so (offset 0x20d000) (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+344)
DEBUG   :     #05 pc 0000000000279244  /system/lib64/libart.so (offset 0x20d000) (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+968)
DEBUG   :     #06 pc 000000000052473c  /system/lib64/libart.so (offset 0x43f000) (MterpInvokeVirtual+588)
DEBUG   :     #07 pc 0000000000547694  /system/lib64/libart.so (offset 0x43f000) (ExecuteMterpImpl+14228)
DEBUG   :     #08 pc 0000000000010ec6  /dev/ashmem/dalvik-DEX data (deleted) (com.xxxx.xxxx.xxxx.doSumInLib+38)
( Other logs ...)

FYI

  • 0x72f74536b8 is the memory address of the function gotten from libcloser.so with dlsym()

SO, JNI crash on doSum calling of libcloser_2.so and the address memory that generates exception is the handle of doSum of libcloser.so opened and closed before opening libcloser_2.so

Anyone can help me?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source