In the ActivityManagerService.java source there is the following comment:
  // Is this the best spot for this? Should we specifically let the
  // other tests below try first and then right before a return
  // is made do we try to apply our checks? That approach might
  // make sense becuase maybe that provider doesn't even exist.

The author is correct in that this is not the correct place. This is because
apps like "com.android.inputmethod.latin" can never run as it needs to load a
dictionary CP as a part of its process. I've therefore added the checkPolicy
call to various return points in the process. It may be that the call should
be added to more places, however the patch works with my simple tests.

The attached patches:
frameworks/base/services/java/com/android/server/am/ActivityManager.java

The main symptom is that the popup keyboards did not work when editing text
and is shown in the logs as:
D/ActivityManager(  336): Denied USE permission between caller=xxx and content 
authority=com.android.inputmethod.latin.dictionarypack
Where caller=xxx is the pid of the com.android.inputmethod.latin app

"com.android.inputmethod.latin.dictionarypack" is defined in:
packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/BinaryDictionary.java
String DICTIONARY_PACK_AUTHORITY = 
"com.android.inputmethod.latin.dictionarypack";

Richard
--- a/ActivityManagerService.java	2013-07-13 12:46:31.000000000 +0100
+++ b/ActivityManagerService.java	2013-07-14 11:48:29.000000000 +0100
@@ -6480,11 +6480,24 @@
         return false;
     }
 
+
+    private void logDeniedAccess(int callerUid, int callerPid, String name, int access) {
+        String srcUid = Integer.toString(callerUid);
+        Slog.d(TAG, "Denied USE permission between caller=" + callerPid +
+               " and content authority=" + name);
+        if (SystemProperties.getBoolean("persist.mmac.enforce", false)) {
+            throw new SecurityException("MMAC Permission Denial: use content provider=" +
+                                        name + " from uid=" + srcUid);
+        }
+    }
+
     private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
             String name, IBinder token, boolean stable, int userId) {
         ContentProviderRecord cpr;
         ContentProviderConnection conn = null;
         ProviderInfo cpi = null;
+        int callerUid = Binder.getCallingUid();
+        int callerPid = Binder.getCallingPid();
 
         synchronized(this) {
             ProcessRecord r = null;
@@ -6498,23 +6511,6 @@
                 }
             }
 
-            // Is this the best spot for this? Should we specifically let the
-            // other tests below try first and then right before a return
-            // is made do we try to apply our checks? That approach might
-            // make sense becuase maybe that provider doesn't even exist.
-            // Here, we check even if the provider string is somethng made up.
-            // Later we would only check if the provider actually does exist.
-            int callerUid = Binder.getCallingUid();
-            if (checkPolicy(callerUid, name, 3) != 0) {
-                String srcUid = Integer.toString(callerUid);
-                Slog.d(TAG, "Denied USE permission between caller=" + Binder.getCallingPid() +
-                       " and content authority=" + name);
-                if (SystemProperties.getBoolean("persist.mmac.enforce", false)) {
-                    throw new SecurityException("MMAC Permission Denial: use content provider=" +
-                                                name + " from uid=" + srcUid);
-                }
-            }
-
             // First check if this content provider has been published...
             cpr = mProviderMap.getProviderByName(name, userId);
             boolean providerRunning = cpr != null;
@@ -6534,6 +6530,9 @@
                     // don't give caller the provider object, it needs
                     // to make its own.
                     holder.provider = null;
+                    if (checkPolicy(callerUid, name, 3) != 0) {
+                        logDeniedAccess(callerUid, callerPid, name, 3);
+                    }
                     return holder;
                 }
 
@@ -6659,6 +6658,9 @@
                     // info and allow the caller to instantiate it.  Only do
                     // this if the provider is the same user as the caller's
                     // process, or can run as root (so can be in any process).
+                    if (checkPolicy(callerUid, name, 3) != 0) {
+                        logDeniedAccess(callerUid, callerPid, name, 3);
+                    }
                     return cpr.newHolder(null);
                 }
 
@@ -6758,6 +6760,9 @@
                 }
             }
         }
+        if (checkPolicy(callerUid, name, 3) != 0) {
+            logDeniedAccess(callerUid, callerPid, name, 3);
+        }
         return cpr != null ? cpr.newHolder(conn) : null;
     }
 

Reply via email to