2

Is it correct for me to assume that, there is no way to make an Android app (APK) to run in root privilege by itself (without an external "su" native executable), even when it is using NDK native code?

I ask because I am assuming since Android apps are not native executables, but instead run in the Dalvik runtime. Hence, there is no way to set "suid bit" on the APK, allowing it to call NDK seteuid(0) and escalate privilege to root?

I'm trying to understand, is that the reason rooted Android device always need the presence of the "su" native executable so that the other app that needs to run some privilege operation can do so by calling something like system() or exec()?

Please feel free to point out if any of my assumption/understanding is incorrect.

1 Answer 1

4

Android assigns different user IDs for each installed application as a privilege separation mechanism. This can be influenced by the certificate that is used to sign an application (https://source.android.com/security/overview/app-security.html#application-signing) in conjunction with the android:sharedUserId attribute in the application's AndroidManifest.xml file:

When an application (APK file) is installed onto an Android device, the Package Manager verifies that the APK has been properly signed with the certificate included in that APK. If the certificate (or, more accurately, the public key in the certificate) matches the key used to sign any other APK on the device, the new APK has the option to specify in the manifest that it will share a UID with the other similarly-signed APKs.

Android applications launched by end users are all spawned from the Zygote process (this is to help speed application launch, since the Zygote can fork and load the application code and not have to reload a bunch of system libraries). At the time of writing this, the Zygote service configuration looks like this:

  service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks

The syntax of this file is outlined here: https://android.googlesource.com/platform/system/core/+/master/init/readme.txt, which has this to say about the privilege levels assigned to services by default (so you can see that by default, Zygote runs as root):

user <username>
  Change to username before exec'ing this service.
  Currently defaults to root.  (??? probably should default to nobody)
  Currently, if your process requires linux capabilities then you cannot use
  this command. You must instead request the capabilities in-process while
  still root, and then drop to your desired uid.

Zygote uses a JNI method named forkAndSpecialize (search for "com_android_internal_os_Zygote.cpp") to handle the platform specific task of calling setuid() to the UID that the Package Manager has assigned based on the manifest and installed applications. Failing to properly exit if that setuid call failed has been the source of Android privilege escalation vulnerabilities in the past (read up on the RageAgainstTheCage exploit if you are interested, although that was not Zygote related).

This is the main reason that you need a separate privileged/setuid binary to launch applications using root level privileges. If you built your own custom system image, you could conceivably modify the PackageManager / Zygote to retain the root privileges, but doing so basically breaks the Android security model.

2
  • Thanks for the detailed explanation. So it is correct to assume that, on a rooted device (which I did not create my custom system image), any Android application would still need the help of an external native suid binary (like "su") to run in root privilege, right? Since the APK would still be forked and loaded by zygote.
    – xyz
    Dec 1, 2015 at 5:32
  • Yes, that's correct. If you're curious how SuperUser.apk or similar work, you can take a look at this related answer: android.stackexchange.com/a/18602/139291
    – Phil Ames
    Dec 1, 2015 at 5:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .