From 6f754e48e95410d00382c9a6b694f0a8a655eb63 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 30 Nov 2016 14:29:59 -0700 Subject: [PATCH] DO NOT MERGE. Grant MMS Uri permissions as the calling UID. 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 (cherry picked from commit 7ff418d9a9afb9ecf42f87fffd3e65477decb55e) --- .../java/android/app/ActivityManagerInternal.java | 9 +++++++++ .../java/com/android/server/MmsServiceBroker.java | 15 +++++++++++++-- .../android/server/am/ActivityManagerService.java | 9 +++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 44b564cb885c0..da856aef112f8 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -16,12 +16,21 @@ package android.app; +import android.content.Intent; + /** * Activity manager local system service interface. * * @hide Only for use within the system server. */ public abstract class ActivityManagerInternal { + /** + * 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. */ diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java index 0de6a03144b5b..469065cef0c6f 100644 --- a/services/core/java/com/android/server/MmsServiceBroker.java +++ b/services/core/java/com/android/server/MmsServiceBroker.java @@ -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; @@ -397,13 +398,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_OWNER) { 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_OWNER); // Grant permission for the carrier app. Intent intent = new Intent(action); @@ -412,7 +421,9 @@ public class MmsServiceBroker extends SystemService { List 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_OWNER); } } finally { Binder.restoreCallingIdentity(token); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6bb1ebfae5e3b..d608f473de176 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -19703,6 +19703,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);