OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
authorJeff Sharkey <jsharkey@android.com>
Wed, 30 Nov 2016 21:29:59 +0000 (14:29 -0700)
committerRubin Xu <rubinxu@google.com>
Thu, 9 Feb 2017 18:03:18 +0000 (18:03 +0000)
A recent security fix prevents the system UID from handing out Uri
permission grants directly from itself.  Instead, services need to
issue grants as the original calling UID to ensure that the caller
actually has access to the Uris.

Test: builds, boots, send/recv MMS works in primary/secondary users
Bug: 33231106
Change-Id: Ia9fe19843b52977c8a94ee5349b907beda1882fc
Merged-In: Ia9fe19843b52977c8a94ee5349b907beda1882fc
(cherry picked from commit 7ff418d9a9afb9ecf42f87fffd3e65477decb55e)

core/java/android/app/ActivityManagerInternal.java
services/core/java/com/android/server/MmsServiceBroker.java
services/core/java/com/android/server/am/ActivityManagerService.java

index d4f80a0..28f8477 100644 (file)
@@ -61,6 +61,13 @@ public abstract class ActivityManagerInternal {
     public static final int APP_TRANSITION_TIMEOUT = 3;
 
     /**
+     * Grant Uri permissions from one app to another. This method only extends
+     * permission grants if {@code callingUid} has permission to them.
+     */
+    public abstract void grantUriPermissionFromIntent(int callingUid, String targetPkg,
+            Intent intent, int targetUserId);
+
+    /**
      * Verify that calling app has access to the given provider.
      */
     public abstract String checkContentProviderAccess(String authority, int userId);
index 33f9234..54b2a25 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.Manifest;
+import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -499,13 +500,21 @@ public class MmsServiceBroker extends SystemService {
          */
         private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
                 int permission) {
+            final Intent grantIntent = new Intent();
+            grantIntent.setData(contentUri);
+            grantIntent.setFlags(permission);
+
+            final int callingUid = Binder.getCallingUid();
             final int callingUserId = UserHandle.getCallingUserId();
             if (callingUserId != UserHandle.USER_SYSTEM) {
                 contentUri = ContentProvider.maybeAddUserId(contentUri, callingUserId);
             }
+
             long token = Binder.clearCallingIdentity();
             try {
-                mContext.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, permission);
+                LocalServices.getService(ActivityManagerInternal.class)
+                        .grantUriPermissionFromIntent(callingUid, PHONE_PACKAGE_NAME,
+                                grantIntent, UserHandle.USER_SYSTEM);
 
                 // Grant permission for the carrier app.
                 Intent intent = new Intent(action);
@@ -514,7 +523,9 @@ public class MmsServiceBroker extends SystemService {
                 List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent(
                         intent);
                 if (carrierPackages != null && carrierPackages.size() == 1) {
-                    mContext.grantUriPermission(carrierPackages.get(0), contentUri, permission);
+                    LocalServices.getService(ActivityManagerInternal.class)
+                            .grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
+                                    grantIntent, UserHandle.USER_SYSTEM);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
index 9cb2042..8185e38 100644 (file)
@@ -21889,6 +21889,15 @@ public final class ActivityManagerService extends ActivityManagerNative
 
     private final class LocalService extends ActivityManagerInternal {
         @Override
+        public void grantUriPermissionFromIntent(int callingUid, String targetPkg, Intent intent,
+                int targetUserId) {
+            synchronized (ActivityManagerService.this) {
+                ActivityManagerService.this.grantUriPermissionFromIntentLocked(callingUid,
+                        targetPkg, intent, null, targetUserId);
+            }
+        }
+
+        @Override
         public String checkContentProviderAccess(String authority, int userId) {
             return ActivityManagerService.this.checkContentProviderAccess(authority, userId);
         }