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 7ff418d9a9)
This commit is contained in:
Jeff Sharkey
2016-11-30 14:29:59 -07:00
committed by Jeff Sharkey
parent 4b0164b27c
commit 3f3da42ef9
3 changed files with 30 additions and 2 deletions

View File

@@ -18,6 +18,7 @@ package android.app;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Intent;
/**
* Activity manager local system service interface.
@@ -25,6 +26,13 @@ import android.content.ComponentName;
* @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.
*/

View 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_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);
@@ -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_OWNER);
}
} finally {
Binder.restoreCallingIdentity(token);

View File

@@ -20585,6 +20585,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);