I recently built libssh2 for Android using OpenSSL as a crypto backend, I also built libcrypto.so and libssl.so myself using the NDK.
In my build process I generate a final libcustom.so linked with libssh2.a.
Google said "If you tried to use your own copy of OpenSSL but forgot to bundle it with your app's APK, the app may run normally on versions of Android platform that includes libcrypto.so. However, the app could crash on later versions of Android that do not include this library (such as, Android 6.0 and later)." that's why I package libcrypto.so, libssl.so and libcustom.so into my APK.
When running an Android app that loads the libcustom.so, my app crashes with the following error:
failed: dlopen failed: cannot locate symbol "EVP_cast5_cbc" referenced by "libcustom.so"... ONLY ON ANDROID 5.
It works well on Android 6 and above.
The symbol EVP_cast5_cbc is undefined but referenced in libssh2.a, but well defined in libcrypto.so.
I don't understand why it runs correctly on Android 6 and above and not on Android 5.
I thought that on Android 5, the libcrypto.so used was not the one I embed in the APK but the one from /system/lib ; so I tried to rename the libcrypto.so and build libssh2.a using the libcrypto renamed, but I am facing the same issue.
Does anybody have an idea ?
Thank's in advance.
Google has changed the use of private libraries for Marshmallow and above; this may be the case that you are experiencing.
Starting in Android 6.0, the system prevents apps from dynamically linking against non-NDK libraries, which may cause your app to crash.
According to this table: https://developer.android.com/about/versions/nougat/android-7.0-changes.html#ndk. You should be able to see logcat warnings when you are running Lollipop with private libraries. For example:
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120
Related
I tried to build 64bit (arm64) Openssl v1.1.1b and add it to my app as shared library (libcrypto.so and libssl.so).
I built standalone toolchain with --arch arm64 and --api 21 arguments, then I built openssl libraries with it and added them to my app.
All 64bit devices with Android 6.x and higher works great, but I am stuck on the Android 5.0.1 64bit – Lenovo TAB 2 A10-70L tablet.
The problem is, that on this specific Android, when I am loading libssl.so, I get error:
E/art ( 2755): dlopen("/data/app/com.myapp.mypackage-1/lib/arm64/libssl.so", RTLD_LAZY) failed:
dlopen failed: cannot locate symbol "EVP_camellia_128_cbc" referenced by "/data/app/com.myapp.mypackage-1/lib/arm64/libssl.so"...
E/MY_APP( 2755): 2019-06-12 14:22:27,984: [MY_APP][18446744071776944368] ERROR (2117) - Error in loading libraries :
dlopen failed: cannot locate symbol "EVP_camellia_128_cbc" referenced by "/data/app/com.myapp.mypackage-1/lib/arm64/libssl.so"...
So exception will be thrown -> loading of other libraries after libssl.so will be not performed and app crashes during or after splashscreen.
I found on StackOverflow, that it can be caused, if you compile native library (as openssl) against higher android version, then the used tablet is… But I make openssl with api 21, that’s Android 5.0, so there shouldn’t be problem. It seems, that openssl expects this symbol in libraries of the device and this device doesn’t have it.
What I tried:
To use different NDK’s to build openssl -> I used 15-19 NDK’s,
with this version I built an app, but the same error occurred (with
“cannot locate symbol”). I tried 12-14 NDK’s to be close to NDK we
are using in our app for other native libs (which is 12b), but with
this NDK I am not able to make openssl libs at all, it will fail
during build.
To use different NDK’s to build whole app -> I
tried 16 and 19, but there were failures in the build and I don’t
think, it would help.
To use 21 as minsdkversion in
AndroidManifests, project-properties and build.gradle files to have
everything in the same api version, but with no success.
I tried built and implement higher version of openssl – 1.1.1c – but the
same error with Camellia occurred.
I tried to add that missing
symbol as a macro to evp.h, but with no success (maybe I should add
it in the different way).
I tried to exclude camellia cipher from
build of openssl by editing makefile, but whole build ended with
error
Why might this be happening, and how can I fix it to run my app on Android 5.x 64bit?
Self solution:)
After all I tried as I mentioned above I found the only solution that worked - build openssl as static library (so libssl.a and libcrypto.a) and add this files to app.
It seems, that dynamic openssl libraries (*.so) does not work for my app, which uses older NDK, but to be honest, I still don't know why.
I have an alljoyn library in my project to pair android devices for a voting app. In old devices the app runs properly but in new devices it stops when it is starting to run.
This is the error, I got:
Caused by: java.lang.UnsatisfiedLinkError: dlopen failed: library "libcrypto.so" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
at java.lang.System.loadLibrary(System.java:1657)
at com.example.nima.voting.alljoyn.peergroupmanager.PeerGroupManager.<clinit>(PeerGroupManager.java:60)
NOTE: I'm not an Android developer.
That said, I found this StackOverflow question, which mentions similar behavior to what you described:
The master Android process is zygote. Its like init in Linux. Zygote
loads OpenSSL when its start, and it loads version 0.9.8. If you link
against OpenSSL 1.0.1, then you will get mysterious runtime crashes.
The crashes are due to the Android loader using the 0.9.8 version of
the library (already mapped from Zygote), and not your version of
OpenSSL.
You can use a shared object, but your shared object must be a wrapper around the static version of libssl and libcrypto.
You mentioned that the app loads properly in old devices but crashes in new devices. If the new devices are linking against OpenSSL v1.0.1 and the old ones against v0.9.8, then this might be the root cause of your problem.
The solution seems to be either to compile against static libraries for libcrypto (and for libssl too, apparently), or to rename these dependencies after the build, then copy them into your precompiled directory (if I interpreted the answer in the link correctly):
The reason is that the system comes with its own (probably different)
version of these shared libraries, and the loader will use
/system/lib/libssl.so and /system/lib/libcrypto.so instead of your
private copies.
I have developed android project using android studio.
It uses android native library which other developer built for speech recognization.
The APK works perfectly when i install on android devices.
I need to put this APK into AOSP because I am going to make android device only for our system. (I have already customized AOSP)
But after adding the APK into AOSP, the APK can not load library.
Error log:
java.lang.UnsatisfiedLinkError: dlopen failed: can't protect segments for "../libsengine.so": Permission denied
Please help me to fix this problem.
If you add your apk into AOSP system/app/ path as a prebuilt app, this might be of help:
Error adding prebuilt apk with shared libraries to AOSP
http://blog.csdn.net/a462533587/article/details/46380795
The problem is the shared library packaged in your apk has never been extracted to /data/app-lib directory, so it can't be linked.
It seems that the library you are using is utilizing some sort of dynamic code loading that is strictly prohibided on Android 26+ (Writable and Executable Segments Enforced for API level >= 26) .
You can read more about the security risk of TEXTREL on the following blog.
I assume that the reason the code works when compiling with Android Studio is because your build.gradle defines a minSdkVersion/targetSdkVersion that does not enforce the TEXTREL check. When compiling via the AOSP make, targetSdkVersion is most probably defined to be the 'current' version where the TEXTREL check is enforced.
These are only assumptions, so I guess you could check or alternatively provide more information such as the platform you are building and the Android.mk + build.gradle files.
I Think This is related to Marshmallow switching from OpenSSL to BoringSSL.
Your exception is occurring in the referenced library code. Contact the vendor for a fix or manually include the OpenSSL libraries to avoid the issue.
You can see this link: https://sourcedna.com/blog/20150806/predicting-app-crashes-on-android-m.html
My problem is the following: I have succesfully built GDAL 1.10.1 using an Android toolchain (CC=i686-linux-android-gcc, CXX=i686-linux-android-c++) that produces the following output libraries libgdal.a, libgdal.la, libgdal.lai, libgdal.so, libgdal.so.1, libgdal.so.1.17.1 in the output folder .libs (in the following I'll call this folder $GDAL_LIB_PATH).
I am trying to build a simple Android app (a simple widget application with a QPushButton named TestAndroid) using Qt 5.4 on Windows. If I don't use GDAL everything works fine and I am able to run my app on an Android emulator for all available platforms: x86, armeabi and armeabi-v7.
Nonetheless, if I try to use GDAL (ex. by simply calling GDALAllRegister() in the initialization of the app) and then linking to libgdal.so the application crashes with the following error:
E/art ( 1614):
dlopen("/data/app/org.qtproject.example.TestAndroid-1/lib/x86/libTestAndroid.so",
RTLD_LAZY) failed: dlopen failed: could not load library
"libgdal.so.1" needed by "libTestAndroid.so"; caused by library
"libgdal.so.1" not found
I have verified that the Android platform is the right one (x86), otherwise the linker would skip the wrong libgdal.so object.
I have included libgdal.so in the *.apk (generated by Qt) using ANDROID_EXTRA_LIBS *= $GDAL_LIB_PATH/libgdal.so. The other files libgdal.so.x.x cannot be included in the same way since Qt prevents it.
In order to avoid dynamic linking I have also tried to link my app with libgdal.a but many link-time errors appears (ex. undefined reference to 'atof')
I have searched on the web but I have not found a solution to my problem.
I am not constrained to use dynamic linking so, a solution to any of the following problems is good for me:
Is there a way to avoid the creation of libgdal.so.x.x files when building GDAL ?
Is there a way to include libgdal.so.x.x files in the *.apk file generated by Qt ?
How can I avoid link-time errors when linking the static library libgdal.a ?
Thanks in advance for any reply!
After several days of trials and errors (mainly errors) I have found a solution to my problem.
I'm writing it as an answer to my question so that it may be helpful to others.
The problem was during the link-time of GDAL. Briefly: the linker created the "real name" shared library libgdal.so.1.17.1 together with the links to it libgdal.so.1 and libgdal.so.
For some reasons (which I ignore) forcing the link to libgdal.so, the linker searches for libgdal.so.1 (which, in turn, would have searched for libgdal.so.1.17.1).
The workaround that solved my problem can be summarized in the following steps:
In the GDAL root, run the ./configure according to the desired configuration (see http://trac.osgeo.org/gdal/wiki/BuildingForAndroid) checking that libtool is ENABLED
Edit the created libtool file (e. g. with gedit) as follows:
replace the value of library_names_spec with library_names_spec="\$libname\${shared_ext}"
replace the value of soname_spec with soname_spec=""
Type make
In the output folder .libs/ the only libgdal.so will be created and now the link to libgdal.so seems to work fine.
Should/does NDK9 work with android API19? (though it was released with API18).
Full story:
I was building an Android App using kivy, python-for-android and buildozer.
compiling with MDK9 (ie 9d) and api19 result in error:
E/AndroidRuntime( 1773): java.lang.UnsatisfiedLinkError: Cannot load library: soinfo_relocate(linker.cpp:975): cannot locate symbol "wait4" referenced by "libpython2.7.so"...
compiling with NDK9 (ie 9d) and API18 works. :)
Just in case anyone stumbles across this. I had the same issue, but building python from scratch using the platform tools, and with NDK r10 and r10b.
It's because google removed an inline wait4() declaration in the NDK platform android-19. The original problem was that wait4() was exposed in the headers but not declared anywhere, so if you tried to use wait4 on older NDKs, you'd probably crash (like you do now).
So they went in and added it to libc.so in API 18 I believe, but libc.so is shipped with the O/S, so devices with O/S older than 18 would not have wait4, so they patched it by adding an inlined wait4() method in NDK platforms up through android-18, then took it out in android-19 I'm not fully sure why yet, seems like it could have made more sense to leave it alone at that point, especially since it's considered an obsolete function. I was told I should not build against android-19 if I wanted the app to run on devices older than API 18, but others say to always use the latest NDK to match your build target. Here is a link to the problem.
https://code.google.com/p/android/issues/detail?id=19854
In my case, I went into the cpython Modules/posixmodule.c file, and added:
#if defined(__ANDROID__)
#undef HAVE_WAIT4
#endif
And in my case that's fine, because none of my python modules use wait4. Indeed, Linux deems the wait4 command obsolete (http://linux.die.net/man/2/wait4). You should instead use the waitpid.
So, even if you download some 3rd party python module that does use wait4, you have 2 options. 1) change that module to use waitpid, or 2) update the Modules/posixmodule.c file inside the "ifdef HAVE_WAIT4" section, and replace the wait4 call with waitpid. The downside is you lose the returned resource usage information, which waitpid doesn't provide, so then if your module needs that, you'd have to add something to retrieve resource usage for that pid separately.
Alternatively, you could remove "wait4" from your configure script if you never plan to use it, and any modules you add that needed it would break, at which point the new engineer working on the problem would have to rediscover all of this over again.
Android SDK are released more often that NDK. It happened more than once that if you use a too recent SDK, the NDK will not have the .h for it. Now i'm not sure this would be related to your issue at all.