Skip to content

Crash: UnsatisfiedLinkError loading OnionMasq JNI at app startup

On the device: Xiaomi Redmi 5, using Android 7.1 (SDK 25) the following crash happened:

Exception java.lang.UnsatisfiedLinkError:
  at java.lang.Runtime.loadLibrary0 (Runtime.java:989)
  at java.lang.System.loadLibrary (System.java:1562)
  at org.torproject.onionmasq.OnionMasqJni.<clinit> (OnionMasqJni.java:202)
  at org.torproject.onionmasq.OnionMasqJni.init
  at org.torproject.onionmasq.OnionMasq.<init> (OnionMasq.java:92)
  at org.torproject.onionmasq.OnionMasq.init (OnionMasq.java:82)
  at org.torproject.vpn.TorApplication.onCreate (TorApplication.kt:15)
  at android.app.Instrumentation.callApplicationOnCreate (Instrumentation.java:1025)
  at android.app.ActivityThread.handleBindApplication (ActivityThread.java:5506)
  at android.app.ActivityThread.-wrap2 (ActivityThread.java)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1593)
  at android.os.Handler.dispatchMessage (Handler.java:102)
  at android.os.Looper.loop (Looper.java:163)
  at android.app.ActivityThread.main (ActivityThread.java:6238)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:904)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:794)

This indicates the expected native .so for oniomasq could not be found or loaded for the device’s ABI.

A Xiaomi Redmi 5 on Android 7.1 (SDK 25) seems to typically run a 32-bit ARM userspace (armeabi-v7a). We do not provide that architecture for onionmasq, so this would be why we got this.

We do build onionmasq for armeabi-v7a, and when I download and unpack the apk, I do find ./lib/armeabi-v7a/libonionmasq_mobile.so in there and:

$ file ./lib/armeabi-v7a/libonionmasq_mobile.so
./lib/armeabi-v7a/libonionmasq_mobile.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, for Android 21, built by NDK r25c (9519653), stripped

I looked at the objdump -p output of the libonionmasq_mobile.so and the libgojni.so for v7a, and the NEEDED shows only system libs (liblog, libdl, libm, libc, and also libandroid for libgojni), which suggests there isn't a missing runtime.

I think if you could run a 32-bit arm emulator of the apk, and capture the logcat, it might be possible to find a missing symbol error when the dlopen happens. Probably there is some symbol/API mismatch and we could see that symbol error in a logcat output from an emulator.... but I'm not that savvy with android, this is just coming from my knowledge of dynamically loaded shared libraries from C.

Edited by micah