3

How does Android perform security checks on native code? Suppose we declare permission X in AndroidManifest.xml, does it mean we inherit that same permission X in our native code?

dacongy
  • 2,504
  • 3
  • 30
  • 48
  • 1
    Should be the case. Some permissions like filesystem permissions are implemented on kernel level so you can't avoid the checks by using native code - others that are implemented on higher levels should get triggered from your code too since native code calls will mostly end up at the same point a java call would too. It might be possible that you find a loophole though. – zapl Aug 10 '12 at 20:35

2 Answers2

2

How does Android perform security checks?

There are basically two ways the permissions are enforced.

  • First of all on kernel level: each installed app is assigned a unique (linux) user id and each time your app is started Android will spawn a process and sets the user id of that process to whatever your app userid is. Now accessing e.g. the filesystem or certain hardware features like network is enforced by using the standard linux group permission system. E.g. access to network is only allowed for a network group and your app user is part of that group if you request the network permission in your manifest.

  • Security in userspace like accessing certain ContentProviders or sending broadcast messages and so on simply can't be relayed to the OS. So once you call a method from either Java or native code you can be (pretty) sure that there is some software check in the end that ensures that you can't do things you have no permission for. The NDK API will most probably simply call (maybe indirectly) some Java method so there is probably no need to have separate checks for native and Java code (but Idk exactly how that is done).

It is likely that you can circumvent some of the Java checks by using native code like networking on the UI thread should work (if you have the network permission). It is also possible that there are loopholes that can only be exploited by using native code but that should be rare. It should not matter in the end what type of code you use.

@user827992

the NDK just produce some digested machine code for the dalvik, there aren't API available in C/C++ for Android; you don't have a problem about using a particular set of API that requires a certain permission because you simply can't even code that and access the API in the first place.

Not true, native code written in C/C++ is at compile time of the app compiled in native machine code for the CPU and at runtime executed directly by the CPU, no dalvik involved. You get back to dalvik if you call some Java method via JNI (through the NDK API) though. Also there is a lot of Android API available through the NDK, thats the reason it exists.

zapl
  • 63,179
  • 10
  • 123
  • 154
  • I don't think that your statement is true, also i don't think that the linux kernel is directly involved at runtime, every application under Android gets its own copy of the Bionic C library, its own copy of the dalvik, and in general terms it is all sandboxed. As far as i know and as far as i have heard from the various talks about Android, you are wrong, also there is no point about involving the kernel when talking about the NDK. – user827992 Aug 10 '12 at 21:30
  • @user827992 The kernel is almost always involved if you execute code. E.g if you do a `File#exists()` in Java or something like `stat`(http://linux.die.net/man/3/stat) in C (which is probably what the Java implementation will call in that case) you ultimately ask the kernel to give you the information via a syscall. You can't sandbox that away, at some point you have to access the real filesystem and therefore the kernel. And it's the kernel that tells you that you don't have access to that file in case your app has no permissions to read it. – zapl Aug 10 '12 at 21:38
  • @zapi i really think that you are wrong, just try to compile a vanilla kernel for Android: surprise, the vanilla kernel is not used under Android, it's an highly patched version of the original Kernel the one that is used under Android, even the compiled object are signed with an ELF from a 32 bit linux object but they are not the usual 32 bit linux objects. The fact that your app access the "real" HDD doesn't mean that you need low level access, your answer doesn't make sense in the Android world, also you can't even mention the classic set of libraries that comes for the C language ... – user827992 Aug 11 '12 at 00:27
  • because Android just adopt Bionic as C library and Bionic works in another way, for example look at this answers http://stackoverflow.com/questions/4930922/android-linux-system-call-list , your statement is true for a standard GNU/Linux distribution not for Android. – user827992 Aug 11 '12 at 00:28
  • @user827992 did you read what you linked there? "Very little is unique to Android. [...] Most of the android additions are drivers (Binder, etc) and novel usage patterns (for example of user IDs) rather than actual syscalls." And http://en.wikipedia.org/wiki/Bionic_%28software%29 is a classic C library just not the one you are used to. – zapl Aug 11 '12 at 23:11
  • @user827992 Yes the vanilla mainline kernel.org kernel does not work for Android because it lacks some additions like more support for the ARM architecture and some Android specific additions. But that does not mean that the kernel is completely different. The kernel you need to build needs to support the hardware of your device and since that is custom made you can't use a general purpose kernel. The ELF format is 32bit ARM so it won't run on your 32bit Intel x86 linux PC. – zapl Aug 11 '12 at 23:48
  • @user827992 - the primary Android kernel changes related to security are the "paranoid networking" group IP check for internet domain sockets (which is a half dozen lines of code), and the removal of System V IPC support which was considered to present a denial of service risk. Pretty much all the rest is built atop existing Linux kernel functionality, much of it generic unix heritage. – Chris Stratton Jan 22 '13 at 22:51
  • Either @user827992 is right or the statements are just adversiment here: http://source.android.com/tech/security/index.html "Since the Application Sandbox is in the kernel, ..." – Karussell Apr 13 '13 at 23:27
  • @Karussell each app is it's own distinct linux user and the kernel kind of sandboxes different users. At least to that extend that one user (or app) can't access files / memory belonging to another one. E.g. data in your private app directory is protected that way. – zapl Apr 15 '13 at 10:08
  • @zapl sorry, I don't get it :) (but I have really only newbie knowledge in this area). Would that mean that one app can change the dalvik VM which runs all other applications like facebook has done? Or has every app its own VM? https://www.facebook.com/notes/facebook-engineering/under-the-hood-dalvik-patch-for-facebook-for-android/10151345597798920 – Karussell Apr 15 '13 at 11:44
  • @Karussell Dalvik VM is AFAIK separate for each app and you can mess with it and break it if you like. Just like in a regular desktop Java application when you start two of them you have two "java" processes running. – zapl Apr 15 '13 at 18:30
-1

According to the "Android logic" there is no point to do that for at least 2 reasons:

  • you always need to code some java lines to make your app, so your entry point will always be the java language and your java app; you can't do an apk with only C/C++ code.
  • the NDK just produce some digested machine code for the dalvik, there aren't API available in C/C++ for Android; you don't have a problem about using a particular set of API that requires a certain permission because you simply can't even code that and access the API in the first place.

In the end just think about an android as a java application where you can code in C/C++ your own business logic for the heavy computational stuff, everything that Google provides you in terms of API and policy is supposed to be related only with the Java language.

user827992
  • 1,743
  • 13
  • 25
  • 1
    Starting with NDK 5 having a Java startup object is not needed: `Developers can also implement the Android application lifecycle in native code with help from the new NativeActivity class.`. also newer NDKs provide rich set of APIs for C++ code. Your knowledge was correct 2 years ago, but things have changed since then. – Eugene Mayevski 'Callback Aug 11 '12 at 08:05
  • 1
    Even when it was written, this answer was incorrect as there were native APIs for access to traditional functionality such as files and sockets from the first release of the ndk (really from the first release of the platform toolchain as the Dalvik vm itself is a native program which depends on these). Also, what prevents native interface to arbitrary Java APIs is their lack of stability and link headers, not any actual protection mechanism which would prevent someone from crafting and issuing calls which work against the private details of a particular Android build. – Chris Stratton Jan 22 '13 at 22:54