Package Android apk with additional executables - android

As a follow up to an earlier question (Android ioctl - root permissions and usage), is it possible to create a separate native executable and package it in an APK?
The app needs root access and isn't going into the Android marketplace, but I'd like to be able to install it without using a script that pushes an extra executable onto the device.

There is an easy way to package an executable into an APK, and let the system installer take care of unpacking this executable, see How to package native commandline application in apk?.
The trick (tested up to Jelly Bean 4.3) is to name the file "libmyexecutable.so" and put it into libs/armeabi of your Android project (I assume an ADT or ant build). The Package Manager will unpack the file to /data/data/your.package.full.name/lib (it's a symbolic link, for backwards compatibility reasons, so maybe in some future version of Android this will not work anymore) on the device, with executable permissions.
Note that the file has all read-and-execute permissions, so you can use Runtime.getRuntime().exec() or system() from other apps, too.
Update:
These days, you should use libs/armeabi-v7a for 32 -bit ARM executables, and you probably need to prepare 64-bit ARM version of the same executables, too.

You can put it into assets and copy it to the app's private directory on first run. After you set the executable bit, you should be able to run it.

Related

What path to put executable to run on Android 29?

My Android app includes a set of executables that are extracted to app directory (/data/data/%package%/) on the first run. It worked just fine if targeted to Android 28 (targetSdkVersion). Since November 2, 2020 it not allowed in Google Play and all the apps must target to 29. So it stopped working with permission exception.
What directory should executables be put to now?
PS. Some similar apps have the same issue.
https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission
When targeting API 29 (Android 10 / Q) or above, it is not possible anymore to have execute permission for files stored within the app's home directory (data), which is exactly what you are describing (/data/data/%package%/).
This Android 10 modification was introduced in commit: https://android-review.googlesource.com/c/platform/system/sepolicy/+/804149 and was then confirmed officially by Google here: https://issuetracker.google.com/issues/128554619
This significant change is being discussed by various projects, in termux/termux-app#1072 for instance. One recommended and (hopefully) future-proof way is to extract program binaries into the application's native lib directory (with android:extractNativeLibs=true), where files can still be executed but are stored read-only for improved security.
Here are examples showing how to handle this change, in Termux with commit f6c3b6f in the android-10 branch or in this other project showing how to run the Erlang runtime on Android by exctrating all the files from a .zip archive into the jniLibs/"abi" subdirectory ("abi" being arm64-v8a for 64-bit ARM, armeabi-v7a for 32-bit ARM, etc.) with the imposed lib___.so filename format expected by the Android platform. Executable files can simply be moved in the right project folder manually, the important part is to use the lib___.so format for the filenames.
In the Android Manifest file, setting the attribute android:extractNativeLibs="true" will get these lib___.so files extracted at installation time in the right native lib directory, with support for execute permission. Symlinks can finally be created if needed in the usual app directory to use the regular executable names, instead of the harder-to-manipulate lib___.so versions.
Thanks, Jérôme

Sdk location in AOSP

Note - I am relatively new to Android and AOSP...
Where can I find the Android SDK in the AOSP? As we know, we build apk files in the android studio using the separately installed SDK. But for some reason, I wish to use the SDK in the AOSP if it is available. I see the source code of SDK in the AOSP; do we need to build it?
Why/How I have arrived at the above question:
I had created an .apk in the AOSP which had JNI files and dependency on some existing Broadcom libs (so). It is a system app. What I noticed is the .apk package does not contain the JNI libs but rather is copied to /system/lib folder separately. Hence I had a doubt how the .apk upgrade will work? Is it possible?
I assumed the .apk upgrade won't work that way and the .apk should be packaged including the JNI libs. Hence I planned to build the .apk in the studio and use the .apk as prebuilt and just sign it in the AOSP (we have the keys). Then I also wanted to allow the developers to build the .apk in AOSP itself by running the Gradle in the command line. I did so by adding the command to the Android.mk. But the point here is, it is still using the SDK installed in /home//Android/Sdk. But there may be build machines which may not have the SDK installed. So I am putting this question - Do we (where?) have the SDK in AOSP? Can I use that instead?
I tried to explain the problem.. in case it's not clear please let me know... Will try to give more details...
OTA update will work. Update with Package Manager - won't. This is normal for system apps with native libraries.
In AOSP applications are built differently depending on their location in build tree. Apps placed in ~/packages/apps and ~/device/some_vendor are system apps and they are handled differently by the system. One of differences is that during build process they are stripped of their native libraries and those libraries are simply copied to the /system/ partition.
Including pre-built apk is a good solution.
Yes you can build sdk yourself from sources. Yes, it's there. But I don't understand why you need that. Are there any changes to the API?
There are other options. For example, you can mangle your build scripts. Say, you can add a global FLAG that would disable lib stripping for system apps.

Porting C based linux application to the Android platform

I have C Linux based application and now I want to port it to Android.
I figured out, that I can extract the toolchain from Android NDK and build my application, but how to make the APK such that I can install it on the android devices without the need of root access.
In Linux, I used to install it using a bash script which used to put my application related files in different folders like /opt, /etc (files shared with other applications) and /var . How can we handle this in Android. Is there a folder similar to /etc in Android where I can put files that other applications can read.
Thanks
-M
First of all, you are lucky if your project compiles "as is" with NDK standalone toolchain. Often, bionic is not enough, and people need to tweak the build environment (from libpthread to full-blown buildroot alternate toolchain with static C runtime).
As for the shared files location, on Android it's named "external storage". Your app and other app may require special permissions to write and read to this location. Directory /opt does not exist here. You don't have write access to /etc, but files like /etc/hosts are available for read.
Regarding the APK. You are right, this is the ultimate way to distribute and install apps on Android. But you can, even without root, to locally install and run a command-line executable. Usually it's done with Developers Options turned on, and enabled USB debugging. Now you can open an adb shell, install and run your program. The trick is that external storage (see above) is marked as 'non-executable'. Therefore, you must find another place for your binary. Usually, /data/local/tmp will be a good choice.
Instead of adb, you can use a terminal emulator on the device.
If you choose to build an APK, you will probably prefer to convert your app to shared library that will perform actions for Java via JNI. But it is also possible to package your command-line binary as part of the APK and use Java Runtime.exec().

Issue including executable with Android application when using Jelly Bean

I have ported a few useful free/open source tools to Android. One is Octave and the other is gnuplot. They work together in unison to provide Matlab like capability for free (as in speech) and free (as in beer). I have packed them inside apps in an interesting way. Specifically,
1) I include the executable and shared libraries inside the libs/armeabi directory. Have to give them funny name because of android naming conventions.
2) I create directories bin/ and mylib/. I give them full permissions.
3) I create links from bin/ to the executable in the unpacked lib/ directory. I give them the correct names and full permissions.
4) I create links from mylib/ to the shared libaries in the unpacked lib/ directory. I give them the correct names and full permissions.
5) I then use ld-linux.so.3 which is one of the libraries now in the mylib/ directory and the--library-path option to point at the mylib/ directory to launch the executable from the Android Terminal Emulator.
Octave works perfectly in all version of Android doing this, but gnuplot gives this error when I attempt to launch it when running Jelly Bean only:
error while loading shared libraries: gnuplot: failed to map segment
from shared object: Operation not permitted.
So, why would I have this error for one of these two executables made the same way? Why only in Jelly Bean? Also, on JB, if I make myself the super user, it all works again.
Any thoughts on how to debug? I have confirmed that all files are there and have the permissions that I intended they have.
Please help. You would be helping a free, open source, educational and useful app if you do.
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.

What are possible causes of "failed to map segment from shared object: operation not permitted", and how to debug?

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

Categories

Resources