atsushieno/fluidsynth-midi-service-j

Binder overwrites native memory area and causes Fatal Signal 11 (SIGSEGV), code 1 (SEGV_MAPPER)

Closed this issue · 6 comments

Something around g_rec_mutex_lock causes crash when it is used as a MidiDeviceService. It does not occur when MidiReceiver instance is directly created within the process...

2018-11-03 22:52:22.527 19771-19794/name.atsushieno.fluidsynthmidideviceservicej A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x400000 in tid 19794 (Thread-4), pid 19771 (ideviceservicej)
2018-11-03 22:52:22.578 19798-19798/? A/DEBUG: pid: 19771, tid: 19794, name: Thread-4  >>> name.atsushieno.fluidsynthmidideviceservicej <<<
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #01 pc 001497e9  /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/lib/x86/libfluidsynth.so (g_rec_mutex_lock+32)
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #02 pc 000b86e1  /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/lib/x86/libfluidsynth.so (fluid_synth_api_enter+177)
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #03 pc 000b9aa6  /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/lib/x86/libfluidsynth.so (fluid_synth_cc+246)
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #04 pc 00010fe9  /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/lib/x86/libjnidispatch.so (ffi_call_SYSV+25)
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #05 pc 00010c60  /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/lib/x86/libjnidispatch.so (ffi_call+176)
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #06 pc 000051e0  /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/lib/x86/libjnidispatch.so
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #07 pc 00007bef  /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/lib/x86/libjnidispatch.so (Java_com_sun_jna_Native_invokeInt+63)
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #15 pc 0014336e  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/split_lib_dependencies_apk.apk (deleted) (com.sun.jna.Function.invoke+838)
2018-11-03 22:52:22.613 19798-19798/? A/DEBUG:     #21 pc 00143562  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/split_lib_dependencies_apk.apk (deleted) (com.sun.jna.Function.invoke+350)
2018-11-03 22:52:22.614 19798-19798/? A/DEBUG:     #27 pc 0014439e  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/split_lib_dependencies_apk.apk (deleted) (com.sun.jna.Library$Handler.invoke+454)
2018-11-03 22:52:22.614 19798-19798/? A/DEBUG:     #54 pc 0000a52c  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/split_lib_slice_4_apk.apk (deleted) (fluidsynth.Synth.cc+92)
2018-11-03 22:52:22.614 19798-19798/? A/DEBUG:     #60 pc 0000f34c  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/name.atsushieno.fluidsynthmidideviceservicej-rqayit337bmxp2uLLi7NVA==/split_lib_slice_6_apk.apk (deleted) (name.atsushieno.fluidsynthmidideviceservicej.FluidsynthMidiReceiver.onSend+324)
2018-11-03 22:52:22.615 19798-19798/? A/DEBUG:     #66 pc 006390b4  /system/framework/boot-framework.vdex (android.media.midi.MidiReceiver.send+34)
2018-11-03 22:52:22.615 19798-19798/? A/DEBUG:     #72 pc 00db71b4  /system/framework/boot-framework.vdex (com.android.internal.midi.MidiDispatcher.onSend+46)
2018-11-03 22:52:22.615 19798-19798/? A/DEBUG:     #78 pc 006390b4  /system/framework/boot-framework.vdex (android.media.midi.MidiReceiver.send+34)
2018-11-03 22:52:22.615 19798-19798/? A/DEBUG:     #84 pc 00638d6c  /system/framework/boot-framework.vdex (android.media.midi.MidiOutputPort$1.run+116)

Looks like the calling Synth Java object points to an invalid pointer. On lldb the relevant fluid_synth_t pointer points to an invalid memory area where the structure fields show some random-ish values. g_rec_mutex_lock() is invoked only if use_mutex field is non-zero, and it becomes some value (7 for my debugging case, it's consistently 7 somehow) even though my explicit settings of the value is 0.

When use_mutex and other fields hold wrong value, the native pointee is still the same address, meaning that the memory is corrupt.

How to find the code which overwrites the fluid_synth_t pointee memory:

  • set breakpoint on Java code e.g. Synth.systemReset() called by the app and run.
  • The Java debugger breaks at the code above. Then, switch to lldb and pause the native execution.
  • Switch to Java debugger and find Synth instance. Copy its h pointer raw value (it should point to the native object).
  • Switch to lldb and add a watch expression (fluid_synth_t*) xxxxxxxx where xxxxxxxx is the raw pointer value copied above.
    • You will have to update this value on every debug execution.
  • Ensure that the pointee has use_mutex value as 0 (as well as the other field values) via the pointer.
  • Select use_mutex item on the pointed field, then choose "Add Watchpoint" command, then add it along with the default dialog settings.
    • Now lldb will stop execution whenever the memory value is being overwritten.
  • Resume native execution.
  • Resume Java execution.

It will break at:

image

This means the binder framework tries to create a parcel and overwrites the memory area which is supposed to be allocated and preserved by the native code...

I went back to basics, i.e. "the pointer is likely reused after the object was disposed"

and indeed it was. It is fixed by removing midi receiver disposal at the call to MidiDeviceService.onStatusChanged(). 1855694