0

Other questions on this topic have been asked here:

Classes for Permission Checks Android

how are android security permissions checked at run-time?

How does Android enforce permissions?

But none of them answer what I am trying to figure out. I want to know where exactly I can find the functions or methods that literally check the permissions I'm requesting to see if I'm allowed to have that permission. More specifically, I want to find out what happens with Android Instant Apps permissions, since IA allows only a fraction of all Android permissions (the list can be found here https://developer.android.com/topic/google-play-instant/faqs).

For them there has to be a check somewhere, a whitelisting method that takes the permissions I'm requesting, understands that my application is an Instant App (rather than a normal one) and so it knows to check what I requested against that limited list only. That way it ensures I cannot ask permissions that are not even supposed to be allowed.

I want to understand and see where this happens, source code of these checks, especially for Instant Apps. I have started from the checkSelfPermissions() function used when implementing the Android Runtime Permissions. Through the function call trace feature in Android Studio and the xref (http://androidxref.com) I went back as much as possible until I found the Context.java file (http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/content/Context.java) which has the prototype declarations with comments for each function.

public abstract int checkPermission(@NonNull String permission, int pid, int uid);

I just don't know where to find the definitions with the actual function body and code for it though. Context.java doesn't have them. And I think I am going more and more down a rabbit hole and a bit too low-level with these: http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/content/pm/PackageManager.java#532

http://androidxref.com/8.1.0_r33/xref/frameworks/native/libs/binder/IPermissionController.cpp#39

http://androidxref.com/8.1.0_r33/xref/frameworks/native/libs/binder/IPermissionController.cpp#39

especially the last two, which not only do I not know if I'm on the right path with them, but I'm trying to figure out that remote()->transact function now and where it's defined, but we're in android native c++ territory now...

Any help or pointers would be immensely appreciated, it shouldn't be that hard to just go through the AOSP source code, right?

Emilian Cebuc
  • 331
  • 4
  • 20
  • 1
    Start here: http://androidxref.com/8.1.0_r33/search?q=InstantApp&project=frameworks and https://developers.google.com/android/reference/com/google/android/gms/instantapps/package-summary – TWL Aug 10 '18 at 16:02
  • that wasn't very helpful I'm afraid, because in the end you've basically given me links to the exact same thing I was looking at already, but I appreciate the thought, I have solved the issue in the end (see my own answer below if interested) – Emilian Cebuc Aug 26 '18 at 18:48

1 Answers1

1

For future reference, in the end I have managed to solve it. It took way longer than I thought, but as it happens with most things, the answer was a lot simplier than thought.Turns out that yes, I was definitely going down lots of rabbit holes, but only up to a point. This whole process of search was actually useful in realizing where the answer would lie.

So the first step was successfully finding the actual proper, "low-level" implementations of the permission check or the permission granting action, and the functions are grantRuntimePermission and checkUidPermission, both in the PackageManagerService.java class. Here are the interesting bits, of each function: http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java#5655

http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java#5335

That is where the checks are being performed, but the system somehow already "knows" about the permission and that it is runtime or not, instant or not. The crucial bit (which also kinda hinted to me what eventually I found the answer to be) is to look at the BasePermission objects created.

I found that the Android OS treats permissions in a more modular way, where each permission, rather than left as a simple string to do a check against, gets transformed into an independent BasePermission object. This gives it a more defined importance, as these objects now contain, besides the permission name, attributes such as the sourcePackage name, permission type, UID that owns the permission, and most importantly, the protectionLevel, amongst others. Here is the BasePermission.java class:

http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/pm/BasePermission.java#23

It seemed that the BasePermission objects get created within each application, based on that application. So in the context of an instant app, the Android OS attributes the permissionLevel to each individual permission object accordingly as it learns the application is, in this case, Instant. Here is the important bit of code:

if (isUidInstantApp) {
   BasePermission bp = mSettings.mPermissions.get(permName);
   if (bp != null && bp.isInstant()) {
       return PackageManager.PERMISSION_GRANTED;
   }
} else {
   return PackageManager.PERMISSION_GRANTED;
}

So it's possible to see how it creates the BasePermission object, based on permName, from a list/array of pre-created permission objects (mSettings.mPermissions) that the System somehow builds for the current application only. This only answers the "where is the permission check made?" question, but now the problem is "how does the system know how to create the BasePermission objects and assign to each of them the correct protectionLevel?". Initially I was completely unable to find where the "mPermissions" list gets populated. Then it hit me: I didn't actually need to know that.

All Android permissions and their names are defined in the global AndroidManifest.xml file. Whenever you use permissions in your application code, you call the Manifest.permission.PERMISSION_NAME string, right? I thought that the manifest would only contains the names of each permission, declared as a string. What I didn't expect was that the only other tiny piece of information the manifest declares is (you guessed it)... a per-permission protectionLevel value. For each permission it would state if it is a "normal" permission as opposed to the "dangerous" ones, as well as if it can be used for instant apps or not. And as expected, only the 10 (at the time of this writing) defined permissions for instant apps from the official docs had the "instant" attribute beside the other available protection levels. Here's one of them: http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/res/AndroidManifest.xml#773

That is how the system knows to build the BasePermission objects, wherever it does that. And there was the whitelisting that I was looking for.

Even if I did look at the manifest as first step in my research, I probably wouldn't have known that the answer was right there in front of me. The knowledge of BasePermission objects was crucial to understand how the permission model and checks are implemented.

Next step now would be to actually find where exactly the system creates the base permission object based on these protection level strings in the manifest. I am guessing there should be an association of those strings to a binary integer such as "normal" or "normal|instant", number which is then used by the BasePermission class to construct the objects' protection level and ultimately define if they're instant.

Emilian Cebuc
  • 331
  • 4
  • 20