From: Tobias Brunner Date: Wed, 17 Jun 2015 13:31:24 +0000 (+0200) Subject: android: Manually load libraries with dlopen() and RTLD_GLOBAL on Android M X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=4391ad7b2698a3efd675085e962955a5be92fa8b;p=thirdparty%2Fstrongswan.git android: Manually load libraries with dlopen() and RTLD_GLOBAL on Android M This fixes an issue when using the Android M preview. Bionic's dynamic linker was changed so that symbols in libraries loaded with RTLD_LOCAL were not found anymore in dlsym(RTLD_DEFAULT, ...). This is the case for libraries loaded with System.loadLibrary(), therefore, the plugin loader in libstrongswan was not able to resolve any symbols defined in other libraries loaded later. While this seems to have been broken unintentionally for existing apps (fix at [1]), it will again be a problem whenever we decide to increase targetSdkVersion beyond 22 (or until that fix makes it into the system/emulator images). Unfortunately, the dynamic loader in releases prior to Android 4.3 can't load libandroidbridge without also loading its dependencies. [1] https://github.com/android/platform_bionic/commit/1913352c6b --- diff --git a/src/frontends/android/jni/libandroidbridge/android_jni.c b/src/frontends/android/jni/libandroidbridge/android_jni.c index 7ab9a24bd6..a6412bdf75 100644 --- a/src/frontends/android/jni/libandroidbridge/android_jni.c +++ b/src/frontends/android/jni/libandroidbridge/android_jni.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2015 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * Hochschule fuer Technik Rapperswil @@ -15,6 +15,8 @@ * for more details. */ +#include + #include "android_jni.h" #include @@ -25,6 +27,21 @@ */ static JavaVM *android_jvm; +static struct { + char name[32]; + void *handle; +} libs[] = { + { "libstrongswan.so", NULL }, +#ifdef USE_BYOD + { "libtncif.so", NULL }, + { "libtnccs.so", NULL }, + { "libimcv.so", NULL }, +#endif + { "libhydra.so", NULL }, + { "libcharon.so", NULL }, + { "libipsec.so", NULL }, +}; + jclass *android_charonvpnservice_class; jclass *android_charonvpnservice_builder_class; android_sdk_version_t android_sdk_version; @@ -79,6 +96,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) JNIEnv *env; jclass jversion; jfieldID jsdk_int; + int i; android_jvm = vm; @@ -87,6 +105,15 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) return -1; } + for (i = 0; i < countof(libs); i++) + { + libs[i].handle = dlopen(libs[i].name, RTLD_GLOBAL); + if (!libs[i].handle) + { + return -1; + } + } + androidjni_threadlocal = thread_value_create(attached_thread_cleanup); android_charonvpnservice_class = @@ -109,6 +136,16 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) */ void JNI_OnUnload(JavaVM *vm, void *reserved) { + int i; + androidjni_threadlocal->destroy(androidjni_threadlocal); + + for (i = countof(libs) - 1; i >= 0; i--) + { + if (libs[i].handle) + { + dlclose(libs[i].handle); + } + } } diff --git a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java index 236e759f89..482caa220a 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java @@ -42,6 +42,7 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.net.VpnService; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -732,22 +733,25 @@ public class CharonVpnService extends VpnService implements Runnable /* * The libraries are extracted to /data/data/org.strongswan.android/... - * during installation. + * during installation. On newer releases most are loaded in JNI_OnLoad. */ static { - System.loadLibrary("strongswan"); - - if (MainActivity.USE_BYOD) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { - System.loadLibrary("tncif"); - System.loadLibrary("tnccs"); - System.loadLibrary("imcv"); - } + System.loadLibrary("strongswan"); + + if (MainActivity.USE_BYOD) + { + System.loadLibrary("tncif"); + System.loadLibrary("tnccs"); + System.loadLibrary("imcv"); + } - System.loadLibrary("hydra"); - System.loadLibrary("charon"); - System.loadLibrary("ipsec"); + System.loadLibrary("hydra"); + System.loadLibrary("charon"); + System.loadLibrary("ipsec"); + } System.loadLibrary("androidbridge"); } }