I have written a .c source code (in Eclipse) which is using libcap library to get information related to network traffic. Now i have created an executable binary by using ndk-build in Eclipse. I have pushed the created binary in libs/armeabi folder to /data/local/ folder of my android (rooted nexus 5, Lollipop) and tried to execute the binary. but android is throwing this error
Error: only position independent executables (PIE) are supported
I don't know anything about PIE, Please tell me how to create a position independent executable.
I don't know anything about PIE, Please tell me how to create a position independent executable.
Position Independent Executable or PIE allows a program to be relocated, just like a shared object. At each run of the program, the program can be loaded at different addresses to make it harder for an attacker to guess certain program state.
You can compile and link a PIE executable in one of two ways. First, compile everything with -fPIE and link with -pie. The second is to compile everything with -fPIC and link with -pie.
If you are building both a shared object and a program, then compile everything with -fPIC. Link the shared object with -shared, and link the program with -pie.
You cannot do it the other way. That is, you cannot compile everything with -fPIE and build both a shared object and a program. For the details, see Code Generation Options in the GCC manual.
One thing to watch out for on Android: building with PIE prior to 4.1 will cause a segmentation fault in /system/bin/linker. PIE was added at Android 4.1, and it crashes lesser versions.
Someone told me to supply a custom link/loader to avoid the problem, but I can't find the reference at the moment.
Also see Security Enhancements in Android 1.5 through 4.1.
Error: only position independent executables (PIE) are supported
Yes, that's a Lollipop feature. See Security Enhancements in Android 5.0.
You can check if a program is built with PIE using readelf:
$ readelf -l my-prog | grep -i "file type"
Elf filetype is DYN (shared object file)
The important part is readelf is reporting DYN, and not reporting EXE. EXE means it lacks PIE, and that should trigger a security related defect.
Related, see Is PIE (Position-independent executable) for main executables supported in Android 4.0 (ICS)?
i know this is an old topic but this hacky way may save some people's time
with a Hex-Editor , find the 17th byte, change the value 02 to 03, and that’s it!
Related
This question already has an answer here:
Forcing CPU/ABI to armeabi-v7a on Android
(1 answer)
Closed 3 years ago.
I found an android app in github, it was written by c++ and use the jni. in its jniLibs i only found the "armeabi-v7a" directory, and all the jni files(.so) were Stored here. my android phone cpu architecture is aarch64(arm-v8a), and the app can run fine on my phone. but after i move the SDK in my own app, it always prompts the error
java.lang.UnsatisfiedLinkError: Native library (com/sun/jna/android-aarch64/libjnidispatch.so) not found in resource path (.)
but at the example app when i remove the same '.so' file it says:
java.lang.UnsatisfiedLinkError: Native library (com/sun/jna/android-arm/libjnidispatch.so) not found in resource path (.)
so, what happen?
Typically, an Android device does support multiple ABI's, and 64 bit devices do support native code build for certain 32 bit architectures.
For instance, arm64(64 bit) devices will always also support armeabi-v7a (32bit), to ensure compatibility with older apps. This is a requirement directly from Google.
For instace, to see which architectures your device supports, run:
Pre-Lolipop:
adb shell getprop ro.product.cpu.abi
Lolipop & higher:
adb shell getprop ro.product.cpu.abilist
You should see a list of several ABI's as the result of the command.
I have read recently a devblog from Realm in which they tackled some JNI-related issues. One of them was similar to what you're facing.
Their conclusion was that Android gets confused when the same app needs to load 64bit & 32bit native libraries, and only tries to load the 64 bit versions, even if a dependency only has the 32bit version of its native code.
In your case, you try to load a native library build for 32bits, but Android tries to load its 64 bit version. This could happen if one of your other dependencies has 64bit native libraries.
The devblog I mentioned: https://academy.realm.io/posts/kenneth-geisshirt-tales-developing-sdks-at-scale/
Search for "More .so Issues"
Hope this helps
Can we enable pie (i.e. Position Independent Executables) for shared libraries in android-ndk r10c? And if yes then how to do it?
I read that we should use PIC for dynamic libraries and PIE for executable but looks like android NDK doesn't support PIC.
I tried enabling -pie flag in LDFLAGS, but i'm getting following error:
/android-ndk-r10c/platforms/android-19/arch-arm/usr/lib/crtbegin_dynamic.o:
in function _start:crtbrand.c(.text+0x8c): error: undefined reference to 'main'
Please help me to solve this as i have read that google will mandate PIE in upcoming android versions so i want my app to be compatible with ANDROID-L+.
The really short story is, if you're building shared libraries (as opposed to executables), you don't need to do anything. Libraries that run on older versions of android will keep on working just fine - nothing has changed in Android 5.0 with respect to this.
The almost as short story is, if you're building executables using Android.mk and targeting Android 4.1+, the necessary flags should be added automatically already.
The full story: The reason why you fail when you try to add the -pie flag to LDFLAGS for libraries, is that this flag is only for executables, not for libraries. When building shared libraries, the compiler flag -fPIC (while building individual object files, if running the compiler manually - Android.mk and ndk-build takes care of this automatically) may be needed on some architectures, but you will notice that it is needed because the linker will refuse to produce a shared library if it's needed and you haven't set it. Thus, if you have an issue you will know already because it will fail to build - if you've built it successfully you don't have any issue.
Similarly when building executables, you need to add -fPIE when building the object files, and -fPIE -pie when linking the executables. Android.mk and ndk-build will take care of this automatically, if your APP_PLATFORM is android-16 (Android 4.1) or higher. Here's the big gotcha - executables built with -pie will only work on android-16 or higher, while executables built without -pie won't work on android-21 (Android 5.0). So there's a grace period here, Android 4.1 to 4.4 will run any executable just fine, while you explicitly need a version without -pie for the older ones and another version with -pie for the newer ones.
If you need to target Android versions prior to 4.1 as well, see https://stackoverflow.com/a/26422855/3115956 for an explanation on how to easily build two versions of your executable.
Can we enable pie (i.e. Position Independent Executables) for shared libraries in android-ndk r10c?
PIE was introduced in Android 4.1/android-16 (see Android <uses-sdk>), but it was optional. See Security Enhancements in Android 1.5 through 4.1. So I think it depends less on the NDK version, and more on the Android version.
When I try to run PIE code on Android 4.0 or below, I get a segfault in /system/bin/linker. That's with an HTC Evo 4G. Your mileage may vary, depending on how robust the link/loader is provided by the OEM. Also see Is PIE (Position-independent executable) for main executables supported in Android 4.0 (ICS)?
Now, PIE is required for Android 5.0 and above. Also see Security Enhancements in Android 5.0.
If you try to compile/link for Android 5.0/android-21 (see Android <uses-sdk>), and without PIE, then you will get a link error. Also see Position Independent Executables and Android Lollipop.
Can we enable pie ... for shared libraries in android-ndk
And a quick word on the obvious (once you know about it). PIC is slightly different than PIE. You use PIE on executable programs, and PIC on shared objects.
If you are building an executable and shared object from the same set of sources and object files, then you would use PIC because PIC works for both (the same is not true of PIE). Also see Position Independent Executables and Android Lollipop.
And if yes then how to do it?
You can compile and link a PIE executable in one of two ways. First, compile everything with -fPIE and link with -pie. The second is to compile everything with -fPIC and link with -pie.
If you are building an executable and shared object from the same set of sources and object files, then you would use PIC because PIC works for both (the same is not true of PIE). Also see Position Independent Executables and Android Lollipop.
I have two executables, both cross compiled to run in Android. I have put both on the device in the same directory. I have put all the shared libraries that they are dependent on in the same directory, including ld-linux.so.3. I run the executables by using:
ld-linux.so.3 --library-path /path/to/libraries executable_name
both work on older versions of Android when running as any user. The both work on the latest version of Android if running as root. Only one works on the latest version of android when running as any user. Instead it gives:
failed to map segment from shared object: executable_name operation not permitted
How can I find out what is different with the executable that won't run?
I read a lot online and most people that get this error, either:
A) don't have execute permissions for one of the libraries they are dependent on or the executable itself.
or
B) are trying to run from a directory that is mounted as NOEXEC.
both of these don't appear to be the case. It can find all libraries and I can load any library by itself and see what other things it is dependent on being resolved. Also, I can run basic scripts from the directories of interest.
The newer version of Android, Jelly Bean, is a different linux kernel version and I wonder if that is related.
What give? How do I debug?
Permission issue. Need to remount /tmp. The following command works for me (Centos 7):
sudo mount /tmp -o remount,exec
I had this error in a different context. For some reason it causes an error when trying to use the /tmp folder.
To solve this I simply:
mkdir tmp
export TMPDIR=`pwd`/tmp
The TMPDIR is a constant that tells where the temporary folder of the system is.
This solutions resolves by creating a directory where we are allowed to and settings this directory into the system. Therefore we can now write to the new system default temporary folder.
The issue was with how the executables were compiled. They needed to be compiled with a cross compiler that properly supported newer arm devices. The compiler I used generated executables that would only work on a subset of arm devices. The issue was not with the different versions of android.
SELinux is enabled by default on Android 4.3, however it is supposed to be "permissive" [0]. Maybe your phone vendor added more restrictive rules.
[0] https://source.android.com/devices/tech/security/se-linux.html
I'm trying to build for an android device and I don't have real SDK/NDK for it. Unlike usual Android devices that have libc.so this one has symbolic link libc.so.6 --> libc-2.7.so.
If I build with regular android NDK-x86 my shared lib (as reported by readelf -d) imports from libc.so which doesn't exist on the device.
What's that numbering is about, how does gcc/ld knows to link to libc.so.6 if I simply say -lc?
To be more specific, that device is an android google tv box (Logitech revue) and it seems that it's a bit different from regular android, my guess it doesn't use retarded bionic and uses normal libc, regular pthread and it's seems to be closer to regular linux.
So, can I use regular android-x86 toolchain to generate code for the google tv device that has different libc? How does it know to link to libc.so.6 instead (so I can tell it what libs to link to?). I tried to simply hardcode these libs at link time, but then I get some problems at runtime (missing symbols, because it used incompatible headers and libs).
What's that numbering is about
You can read about external library versioning here.
how does gcc/ld knows to link to libc.so.6 if I simply say -lc?
On Linux with glibc, the libc.so is actually a linker script, containing something like:
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a
AS_NEEDED ( /lib/ld-linux-x86-64.so.2 ) )
So, can I use regular android-x86 toolchain to generate code for the google tv device that has different libc?
No, you need a cross-compiler for this. A cross-compiler is one that runs on one OS (regular Linux here), but creates an executable that will run somewhere else (on Google V).
Your best bet is to download SDK for GoogleTV, which will include such a cross-compiler, as well as required libraries.
I want to use some unix tools on my rooted android arm6 based phone. I will be using cross compiler tools provided here. If I want to compile gnu netcat, how can I set the cross compiler prefix to arm-none-linux-gnueabi- and how to enable static linking (no shared library).
I managed to cross-compile rsync for Android using Ubuntu's arm-linux-gnueabi toolchain. See this related question.
Unless you particularly need to build against a more standard libc than bionic, you can just use the ndk's toolchain, either by copying the hello-jni example and changing BUILD_SHARED_LIBRARY to BUILD_EXECUTABLE in the jni/Android.mk or using the script to generate a stand alone toolchain. You may want to use the V=1 option to the ndk-build script to see the commands it's issuing to its gcc.
Otherwise you may need to pass the prefix to the configure script or manually edit it into the Makefile for the project. This often has not gone well as many projects have make systems not really set up for cross compiling, I've had to resort to editing the configure script to set prefixes and skip tests where it tries to execute a test program.
An option that sometimes works when the build system is more complicated than the project requires is to do a configure for your host (let's hope that's linux). Then manually edit the generated Makefile to change anything needed to build for android instead. Might not be a bad idea to do a clean just in case (especially if you did a test host build). And then do the build which will pick up the arm compiler from your Makefile modifications.
Lastly, if you can be content with the original netcat by Hobbit rather than the gnu version, you hardly need to port it to android yourself as that's already been done. There's already an android version in the google tree at https://android.googlesource.com/platform/external/netcat
which may be on your device already (as 'nc'), and is definitely included in alternate ROMs such as Cyanogenmod.