am 8be305dd: Merge "Also check app-ops on path-permissions." into mnc-dev

* commit '8be305dd6582f154c5a5894034a35fc8ec225b71':
  Also check app-ops on path-permissions.
This commit is contained in:
Jeff Sharkey
2015-07-25 02:20:25 +00:00
committed by Android Git Automerger
2 changed files with 71 additions and 41 deletions

View File

@@ -16,8 +16,11 @@
package android.content; package android.content;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
@@ -40,8 +43,8 @@ import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.Process; import android.os.Process;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Log;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import java.io.File; import java.io.File;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@@ -474,15 +477,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken) private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken)
throws SecurityException { throws SecurityException {
enforceReadPermissionInner(uri, callerToken); final int mode = enforceReadPermissionInner(uri, callingPkg, callerToken);
if (mode != MODE_ALLOWED) {
final int permOp = AppOpsManager.permissionToOpCode(mReadPermission);
if (permOp != AppOpsManager.OP_NONE) {
final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg);
if (mode != AppOpsManager.MODE_ALLOWED) {
return mode; return mode;
} }
}
if (mReadOp != AppOpsManager.OP_NONE) { if (mReadOp != AppOpsManager.OP_NONE) {
return mAppOpsManager.noteProxyOp(mReadOp, callingPkg); return mAppOpsManager.noteProxyOp(mReadOp, callingPkg);
@@ -493,15 +491,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken) private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken)
throws SecurityException { throws SecurityException {
enforceWritePermissionInner(uri, callerToken); final int mode = enforceWritePermissionInner(uri, callingPkg, callerToken);
if (mode != MODE_ALLOWED) {
final int permOp = AppOpsManager.permissionToOpCode(mWritePermission);
if (permOp != AppOpsManager.OP_NONE) {
final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg);
if (mode != AppOpsManager.MODE_ALLOWED) {
return mode; return mode;
} }
}
if (mWriteOp != AppOpsManager.OP_NONE) { if (mWriteOp != AppOpsManager.OP_NONE) {
return mAppOpsManager.noteProxyOp(mWriteOp, callingPkg); return mAppOpsManager.noteProxyOp(mWriteOp, callingPkg);
@@ -518,26 +511,47 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
== PERMISSION_GRANTED; == PERMISSION_GRANTED;
} }
/**
* Verify that calling app holds both the given permission and any app-op
* associated with that permission.
*/
private int checkPermissionAndAppOp(String permission, String callingPkg,
IBinder callerToken) {
if (getContext().checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid(),
callerToken) != PERMISSION_GRANTED) {
return MODE_ERRORED;
}
final int permOp = AppOpsManager.permissionToOpCode(permission);
if (permOp != AppOpsManager.OP_NONE) {
return mTransport.mAppOpsManager.noteProxyOp(permOp, callingPkg);
}
return MODE_ALLOWED;
}
/** {@hide} */ /** {@hide} */
protected void enforceReadPermissionInner(Uri uri, IBinder callerToken) protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken)
throws SecurityException { throws SecurityException {
final Context context = getContext(); final Context context = getContext();
final int pid = Binder.getCallingPid(); final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid();
String missingPerm = null; String missingPerm = null;
int strongestMode = MODE_ALLOWED;
if (UserHandle.isSameApp(uid, mMyUid)) { if (UserHandle.isSameApp(uid, mMyUid)) {
return; return MODE_ALLOWED;
} }
if (mExported && checkUser(pid, uid, context)) { if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getReadPermission(); final String componentPerm = getReadPermission();
if (componentPerm != null) { if (componentPerm != null) {
if (context.checkPermission(componentPerm, pid, uid, callerToken) final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken);
== PERMISSION_GRANTED) { if (mode == MODE_ALLOWED) {
return; return MODE_ALLOWED;
} else { } else {
missingPerm = componentPerm; missingPerm = componentPerm;
strongestMode = Math.max(strongestMode, mode);
} }
} }
@@ -551,14 +565,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
for (PathPermission pp : pps) { for (PathPermission pp : pps) {
final String pathPerm = pp.getReadPermission(); final String pathPerm = pp.getReadPermission();
if (pathPerm != null && pp.match(path)) { if (pathPerm != null && pp.match(path)) {
if (context.checkPermission(pathPerm, pid, uid, callerToken) final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken);
== PERMISSION_GRANTED) { if (mode == MODE_ALLOWED) {
return; return MODE_ALLOWED;
} else { } else {
// any denied <path-permission> means we lose // any denied <path-permission> means we lose
// default <provider> access. // default <provider> access.
allowDefaultRead = false; allowDefaultRead = false;
missingPerm = pathPerm; missingPerm = pathPerm;
strongestMode = Math.max(strongestMode, mode);
} }
} }
} }
@@ -566,7 +581,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
// if we passed <path-permission> checks above, and no default // if we passed <path-permission> checks above, and no default
// <provider> permission, then allow access. // <provider> permission, then allow access.
if (allowDefaultRead) return; if (allowDefaultRead) return MODE_ALLOWED;
} }
// last chance, check against any uri grants // last chance, check against any uri grants
@@ -575,7 +590,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
? maybeAddUserId(uri, callingUserId) : uri; ? maybeAddUserId(uri, callingUserId) : uri;
if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION,
callerToken) == PERMISSION_GRANTED) { callerToken) == PERMISSION_GRANTED) {
return; return MODE_ALLOWED;
}
// If the worst denial we found above was ignored, then pass that
// ignored through; otherwise we assume it should be a real error below.
if (strongestMode == MODE_IGNORED) {
return MODE_IGNORED;
} }
final String failReason = mExported final String failReason = mExported
@@ -587,25 +608,27 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
} }
/** {@hide} */ /** {@hide} */
protected void enforceWritePermissionInner(Uri uri, IBinder callerToken) protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken)
throws SecurityException { throws SecurityException {
final Context context = getContext(); final Context context = getContext();
final int pid = Binder.getCallingPid(); final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid();
String missingPerm = null; String missingPerm = null;
int strongestMode = MODE_ALLOWED;
if (UserHandle.isSameApp(uid, mMyUid)) { if (UserHandle.isSameApp(uid, mMyUid)) {
return; return MODE_ALLOWED;
} }
if (mExported && checkUser(pid, uid, context)) { if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getWritePermission(); final String componentPerm = getWritePermission();
if (componentPerm != null) { if (componentPerm != null) {
if (context.checkPermission(componentPerm, pid, uid, callerToken) final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken);
== PERMISSION_GRANTED) { if (mode == MODE_ALLOWED) {
return; return MODE_ALLOWED;
} else { } else {
missingPerm = componentPerm; missingPerm = componentPerm;
strongestMode = Math.max(strongestMode, mode);
} }
} }
@@ -619,14 +642,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
for (PathPermission pp : pps) { for (PathPermission pp : pps) {
final String pathPerm = pp.getWritePermission(); final String pathPerm = pp.getWritePermission();
if (pathPerm != null && pp.match(path)) { if (pathPerm != null && pp.match(path)) {
if (context.checkPermission(pathPerm, pid, uid, callerToken) final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken);
== PERMISSION_GRANTED) { if (mode == MODE_ALLOWED) {
return; return MODE_ALLOWED;
} else { } else {
// any denied <path-permission> means we lose // any denied <path-permission> means we lose
// default <provider> access. // default <provider> access.
allowDefaultWrite = false; allowDefaultWrite = false;
missingPerm = pathPerm; missingPerm = pathPerm;
strongestMode = Math.max(strongestMode, mode);
} }
} }
} }
@@ -634,13 +658,19 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
// if we passed <path-permission> checks above, and no default // if we passed <path-permission> checks above, and no default
// <provider> permission, then allow access. // <provider> permission, then allow access.
if (allowDefaultWrite) return; if (allowDefaultWrite) return MODE_ALLOWED;
} }
// last chance, check against any uri grants // last chance, check against any uri grants
if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
callerToken) == PERMISSION_GRANTED) { callerToken) == PERMISSION_GRANTED) {
return; return MODE_ALLOWED;
}
// If the worst denial we found above was ignored, then pass that
// ignored through; otherwise we assume it should be a real error below.
if (strongestMode == MODE_IGNORED) {
return MODE_IGNORED;
} }
final String failReason = mExported final String failReason = mExported

View File

@@ -640,7 +640,7 @@ public abstract class DocumentsProvider extends ContentProvider {
final Bundle out = new Bundle(); final Bundle out = new Bundle();
try { try {
if (METHOD_CREATE_DOCUMENT.equals(method)) { if (METHOD_CREATE_DOCUMENT.equals(method)) {
enforceWritePermissionInner(documentUri, null); enforceWritePermissionInner(documentUri, getCallingPackage(), null);
final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE); final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME); final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
@@ -654,7 +654,7 @@ public abstract class DocumentsProvider extends ContentProvider {
out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri); out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
} else if (METHOD_RENAME_DOCUMENT.equals(method)) { } else if (METHOD_RENAME_DOCUMENT.equals(method)) {
enforceWritePermissionInner(documentUri, null); enforceWritePermissionInner(documentUri, getCallingPackage(), null);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME); final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
final String newDocumentId = renameDocument(documentId, displayName); final String newDocumentId = renameDocument(documentId, displayName);
@@ -678,7 +678,7 @@ public abstract class DocumentsProvider extends ContentProvider {
} }
} else if (METHOD_DELETE_DOCUMENT.equals(method)) { } else if (METHOD_DELETE_DOCUMENT.equals(method)) {
enforceWritePermissionInner(documentUri, null); enforceWritePermissionInner(documentUri, getCallingPackage(), null);
deleteDocument(documentId); deleteDocument(documentId);
// Document no longer exists, clean up any grants // Document no longer exists, clean up any grants