Permission denied on exec() from a binary running as root - android

I have a C binary that I run using root user (su -c binary_path) in Android.
Everything works fine until the binary tries to exec*() another binary. It actually works on most devices, however on some I get EACCES error.
The C binary is actually started using this:
execlp("su","su","-c",binary_path,NULL);
At some point, the binary will try to make those calls (simplified):
fork();
...
// child here
execlp("sh","sh","-c",script,NULL);
Actually tested on different Android 6.0 devices, a Nexus 9 and a S7. Nexus 9 ok, S7 fails.
So I checked all permissions and security context of the following, found no difference:
/system/bin
/system/bin/sh
/system/bin/ls
<library_path>
/su/bin/su
Also checked the binary was running with UID/GID = 0, true on both devices.
In logcat, I don't see any audit for a missing permission or secure policy violation.
EDIT: Just verified the security context the binary is running under:
$ps -Z
u:r:init:s0 root ...
Same for both devices whether exec() works or not.
EDIT2: On the device it fails, /proc/kmsg contains this when trying to exec():
Restricted making process. PID = 8868(<binary>) PPID = 8340(<binary>)
No avc from selinux, and this text cannot be found in AOSP source code.

After searching for "Restricted making process" on Google, I stumbled across Samsung kernels for the S5 and S6 (not the S7).
if(CHECK_ROOT_UID(current))
if(sec_restrict_fork())
{
PRINT_LOG("Restricted making process. PID = %d(%s) "
"PPID = %d(%s)\n",
current->pid, current->comm,
current->parent->pid, current->parent->comm);
return -EACCES;
}
And the sec_restrict_fork() contains this:
if (sec_check_execpath(current->mm, "/data/")) {
ret = 1;
goto out;
}
Hence the failure on Samsung devices and no others.

Related

Android Cuttlefish Device Not Booting - launch_cvd Command Not Working (Error: run_cvd returned 23)

I have built a custom ROM that I'm testing on Android Cuttlefish, but when I go to boot the device on the command line using the launch_cvd command, I get the following errors:
[assemble_cvd ... fetcher_config.cpp:212] Could not find file ending in kernel
[assemble_cvd ... fetcher_config.cpp 212] Could not find file ending in initramfs.img
run_cvd returned 23
Subprocess 39641 exited with error code: 23
The main issue seems to lie in the 'error 23' that is returned by run_cvd.
I have tried Google searching and browsing popular forums where Android is built and debugged (XDA Forums, Reddit, StackOverflow, the Android Building Google Group, YouTube, and the web in general). I have also posted on Reddit and will post on the Android Building Google Group. Additionally, I have looked through the source code for Cuttlefish on Google's Git repo to find why the program is outputting the error to no avail.
Lastly, I read through the logfiles of Cuttlefish to see the errors outputted by Cuttlefish. The kernel.log file seems to show the kernel booted successfully (despite the command line saying that it couldn't find the kernel file), I would imagine the same is true of initramfs.img, but I have no way of confirming that initramfs.img was successfully found by launch_cvd. The logcat file is empty (likely because the Cuttlefish failed to boot) and launcher.log simply reproduces the output on the command line (which contain the four errors I listed above).
Could anyone help me troubleshoot this issue? Your help would be greatly appreciated!
Do ps -A | grep crosvm to see if crosvm is running already.
If it is do stop_cvd || true or kill crosvm process with process PID.

Android: Why doesn't native binary have access to the internet, while my Android application does

I importing a native binary that is started from an Android application that was done as more or less described in:
Compile and use ABI-dependent executable binaries in Android with Android Studio 2.2 and CMake
Then I start the binary with Runtime.getRuntime().exec()
The problem is that the binary cannot access the internet, while the Java application can. To compare:
java.lang.Runtime.getRuntime().exec("ping -c 1 nu.nl");
works (returns 0), while ...
res = system("/system/bin/ping -c nu.nl");
...doesn't work, it returns 512 (which is supposed to be right-bit-shifted with 8, which means ping returns the exit code 2)
Why doesn't this work?
Obviously the manifest file contains:
uses-permission android:name="android.permission.INTERNET"
As pointed out in the comments, I made an embarrassing typo in the C code,..
/system/bin/ping -c nu.nl
should have been
/system/bin/ping -c 1 nu.nl
(I did have connection problems as pointed out by a linked in curl library, but now curl isn't complaining about that anymore)

Android ART - Usage of .oat file in /dalvik-cache/?

while playing around with Android ART and the "native" code file .oat/.elf which is created at the app installation process, I did notice something odd.
For my understanding, if the device is using ART (Android >= 5.0), the app will start with the compiled oat file (/data/dalvik-cache/arm64/).
Thats why I was kinda surprised when checking the used fd's of an app and did not find the file there. Only the normal apk (/data/app//base.apk) is listed there.
Check this output of my "ls -l /proc/PID/fd"
So I thought maybe it's just not listed there. So I did exchange the oat file of that app by myself by compiling another classes.dex with the dex2oat tool.
So even after changing the file, the app starts normally without any strange messages or errors (also in logcat).
What is the explanation for this? What is the detailed process Android does when starting an app under ART?
I hope someone can clear that up for me. Thanks a lot.
Based on #Paschalis comment, I investigated here and the oat file is indeed memory mapped on Android 5.0 devices (emulator):
a6af4000-a6af9000 r--p 00000000 1f:01 7366 /data/dalvik-cache/x86/data#app#my.app.works-1#base.apk#classes.dex
Check via:
cat /proc/<PID>/maps | grep dex
Sadly this isn't true anymore for Android 6.0 devices (Nexus 5 & arm-Emulator).
The odex file is within the /data/app/<APP>/oat/<ARCHITECTURE>/ folder as 'base.odex`
/data/app/app.app.works-1/oat/arm/base.odex
I still haven't found a valid reference for this, it is based on experiments and observations

Android insmod kernel object on boot

I am currently trying to insmod a kernel module during the end of the boot process, and so I've created the following entries in init.rc:
on post_late_start
start myscript
on nonencrypted
class_start late_start
trigger post_late_start
on property:void.decrypt=trigger_restart_framework
class_start main
class_start late_start
trigger post_late_start
service myscript /data/my_sh.sh
disabled
oneshot
Then in my /data directory my_sh.sh has the following:
#!/system/bin/sh
log -t mytag -p V "Hello World!"
insmod mymodule.ko mod_parameter=arg
But when I run -- sometimes I do not see the "Hello World" tag when I logcat -s "mytag" and of course, the insmodded module is not installed either.
What is the proper way of late-inserting a kernel module (it needs to go in after network is up and /data is mounted). And further -- how do I get the output of insmod into the log so that I can debug? Any help is appreciated and I can post more details if necessary.
At least since Froyo and still in Lollipop, Android init implements insmod in system/core/init/buildin.c. It is supposed to work directly in an init*.rc file:
on boot
insmod /system/lib/modules/your-module.ko.
However, at least in Lollipop 5.1, it no longer works, as SELinux rules are enforced. init does not have the required sys_module permission. Therefore the underlying init_module system call returns EPERM. This is never reported to anywhere. The only symptom is that insmod commands now fail to load the module, always.
I opened an AOSP issue on this. According to Google, this works as intended. If you want to use kernel modules when SELinux is enforced (which they strongly advice against), you must yourself add the required SELinux permission to init.
I am not sure about your log, but to insmod you need to give the exact path to the module, because I dont think you will be having mymodule.ko residing in the same place as init.rc is there. So try to give the full path of your ko file.
Generally it resides in /lib/modules/youdrivername.ko
so check it here first.

unhandled page fault (11) at 0x0000000c, code 0x017

I am trying to start a native app from within an android app (Android Jelly bean (4.1.2)). I am able to start the native app manually from adb, however it does not start from android. The native app is inside AsyncTask and it is started by the doInBackground function. The command I use to start the app inside android is:
process = Runtime.getRuntime().exec("/data/data/MyAppDir/CAL_Android > /data/data/MyAppDir/out.txt 2>&1 &");
I simplified the command as below, but still did not start:
process = Runtime.getRuntime().exec("/data/data/MyAppDir/CAL_Android");
My various attempts at debugging the issue:
Start a simple command, like "touch file.txt" from android. Works
Moved the native app to /data/local/tmp. Did not work.
Changed the execute permission to 777 (rwxrwxrwx). Did not work.
Changed the owner to root apart from that of the app. Did not work.
Tried using a thread (implements Runnable instead of extends AsyncTask). Did not work.
Execute command using "su -c" ("su -c /data/data/MyAppDir/CAL_Android"). Did not work.
Place the command to execute inside a shell script and invoke shell script from Android. Did not work.
I checked the dmesg output and the error I get is:
<7>[14156.022980] CAL_Android: unhandled page fault (11) at 0x0000000c, code 0x017
<1>[14156.023010] pgd = e6204000
<1>[14156.026306] [0000000c] *pgd=b0728831, *pte=00000000, *ppte=00000000
<4>[14156.032777]
<4>[14156.034242] Pid: 9408, comm: CAL_Android
<4>[14156.051821] CPU: 0 Tainted: G W (3.4.0-ge11b2fc-dirty #1)
<4>[14156.061557] PC is at 0x4012aa22
Can someone please tell me what the problem is?
EDIT:
The dmesg output is not correct. After checking a few more times, I am not getting the error message in dmesg. The crash seems to have happened due to a different unknown reason. But I have added an answer to the reason for not being able to start the native app from android. Hopefully this helps someone who faces a similar issue.
I found out why the android app was not able to start the native app, by using the below 2 lines and printing them in the log.
BufferedReader std_input = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader std_error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
while ((line = std_error.readLine()) != null) {
Log.i(TAG, line);
}
When I used "su -c" before my command, I got this error message:
su: uid <xyz> not allowed to su
and when I did not use "su -c" I got this one instead:
"Cannot open socket: Operation not permitted"
The reason is that, the android app does not have root permission to start the native app and the native app needs root permission to open a socket for sending and receiving data.

Categories

Resources