Loading core/java/android/content/ContentProvider.java +68 −38 Original line number Diff line number Diff line Loading @@ -16,8 +16,11 @@ package android.content; import static android.content.pm.PackageManager.PERMISSION_GRANTED; 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.Nullable; Loading @@ -40,8 +43,8 @@ import android.os.OperationCanceledException; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.UserHandle; import android.util.Log; import android.text.TextUtils; import android.util.Log; import java.io.File; import java.io.FileDescriptor; Loading Loading @@ -474,15 +477,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 { private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken) throws SecurityException { enforceReadPermissionInner(uri, callerToken); final int permOp = AppOpsManager.permissionToOpCode(mReadPermission); if (permOp != AppOpsManager.OP_NONE) { final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg); if (mode != AppOpsManager.MODE_ALLOWED) { final int mode = enforceReadPermissionInner(uri, callingPkg, callerToken); if (mode != MODE_ALLOWED) { return mode; } } if (mReadOp != AppOpsManager.OP_NONE) { return mAppOpsManager.noteProxyOp(mReadOp, callingPkg); Loading @@ -493,15 +491,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 { private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken) throws SecurityException { enforceWritePermissionInner(uri, callerToken); final int permOp = AppOpsManager.permissionToOpCode(mWritePermission); if (permOp != AppOpsManager.OP_NONE) { final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg); if (mode != AppOpsManager.MODE_ALLOWED) { final int mode = enforceWritePermissionInner(uri, callingPkg, callerToken); if (mode != MODE_ALLOWED) { return mode; } } if (mWriteOp != AppOpsManager.OP_NONE) { return mAppOpsManager.noteProxyOp(mWriteOp, callingPkg); Loading @@ -518,26 +511,47 @@ public abstract class ContentProvider implements ComponentCallbacks2 { == 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} */ protected void enforceReadPermissionInner(Uri uri, IBinder callerToken) protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); String missingPerm = null; int strongestMode = MODE_ALLOWED; if (UserHandle.isSameApp(uid, mMyUid)) { return; return MODE_ALLOWED; } if (mExported && checkUser(pid, uid, context)) { final String componentPerm = getReadPermission(); if (componentPerm != null) { if (context.checkPermission(componentPerm, pid, uid, callerToken) == PERMISSION_GRANTED) { return; final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { missingPerm = componentPerm; strongestMode = Math.max(strongestMode, mode); } } Loading @@ -551,14 +565,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 { for (PathPermission pp : pps) { final String pathPerm = pp.getReadPermission(); if (pathPerm != null && pp.match(path)) { if (context.checkPermission(pathPerm, pid, uid, callerToken) == PERMISSION_GRANTED) { return; final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { // any denied <path-permission> means we lose // default <provider> access. allowDefaultRead = false; missingPerm = pathPerm; strongestMode = Math.max(strongestMode, mode); } } } Loading @@ -566,7 +581,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { // if we passed <path-permission> checks above, and no default // <provider> permission, then allow access. if (allowDefaultRead) return; if (allowDefaultRead) return MODE_ALLOWED; } // last chance, check against any uri grants Loading @@ -575,7 +590,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 { ? maybeAddUserId(uri, callingUserId) : uri; if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, 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 Loading @@ -587,25 +608,27 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } /** {@hide} */ protected void enforceWritePermissionInner(Uri uri, IBinder callerToken) protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); String missingPerm = null; int strongestMode = MODE_ALLOWED; if (UserHandle.isSameApp(uid, mMyUid)) { return; return MODE_ALLOWED; } if (mExported && checkUser(pid, uid, context)) { final String componentPerm = getWritePermission(); if (componentPerm != null) { if (context.checkPermission(componentPerm, pid, uid, callerToken) == PERMISSION_GRANTED) { return; final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { missingPerm = componentPerm; strongestMode = Math.max(strongestMode, mode); } } Loading @@ -619,14 +642,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 { for (PathPermission pp : pps) { final String pathPerm = pp.getWritePermission(); if (pathPerm != null && pp.match(path)) { if (context.checkPermission(pathPerm, pid, uid, callerToken) == PERMISSION_GRANTED) { return; final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { // any denied <path-permission> means we lose // default <provider> access. allowDefaultWrite = false; missingPerm = pathPerm; strongestMode = Math.max(strongestMode, mode); } } } Loading @@ -634,13 +658,19 @@ public abstract class ContentProvider implements ComponentCallbacks2 { // if we passed <path-permission> checks above, and no default // <provider> permission, then allow access. if (allowDefaultWrite) return; if (allowDefaultWrite) return MODE_ALLOWED; } // last chance, check against any uri grants if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 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 Loading core/java/android/provider/DocumentsProvider.java +3 −3 Original line number Diff line number Diff line Loading @@ -640,7 +640,7 @@ public abstract class DocumentsProvider extends ContentProvider { final Bundle out = new Bundle(); try { if (METHOD_CREATE_DOCUMENT.equals(method)) { enforceWritePermissionInner(documentUri, null); enforceWritePermissionInner(documentUri, getCallingPackage(), null); final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE); final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME); Loading @@ -654,7 +654,7 @@ public abstract class DocumentsProvider extends ContentProvider { out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri); } 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 newDocumentId = renameDocument(documentId, displayName); Loading @@ -678,7 +678,7 @@ public abstract class DocumentsProvider extends ContentProvider { } } else if (METHOD_DELETE_DOCUMENT.equals(method)) { enforceWritePermissionInner(documentUri, null); enforceWritePermissionInner(documentUri, getCallingPackage(), null); deleteDocument(documentId); // Document no longer exists, clean up any grants Loading Loading
core/java/android/content/ContentProvider.java +68 −38 Original line number Diff line number Diff line Loading @@ -16,8 +16,11 @@ package android.content; import static android.content.pm.PackageManager.PERMISSION_GRANTED; 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.Nullable; Loading @@ -40,8 +43,8 @@ import android.os.OperationCanceledException; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.UserHandle; import android.util.Log; import android.text.TextUtils; import android.util.Log; import java.io.File; import java.io.FileDescriptor; Loading Loading @@ -474,15 +477,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 { private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken) throws SecurityException { enforceReadPermissionInner(uri, callerToken); final int permOp = AppOpsManager.permissionToOpCode(mReadPermission); if (permOp != AppOpsManager.OP_NONE) { final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg); if (mode != AppOpsManager.MODE_ALLOWED) { final int mode = enforceReadPermissionInner(uri, callingPkg, callerToken); if (mode != MODE_ALLOWED) { return mode; } } if (mReadOp != AppOpsManager.OP_NONE) { return mAppOpsManager.noteProxyOp(mReadOp, callingPkg); Loading @@ -493,15 +491,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 { private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken) throws SecurityException { enforceWritePermissionInner(uri, callerToken); final int permOp = AppOpsManager.permissionToOpCode(mWritePermission); if (permOp != AppOpsManager.OP_NONE) { final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg); if (mode != AppOpsManager.MODE_ALLOWED) { final int mode = enforceWritePermissionInner(uri, callingPkg, callerToken); if (mode != MODE_ALLOWED) { return mode; } } if (mWriteOp != AppOpsManager.OP_NONE) { return mAppOpsManager.noteProxyOp(mWriteOp, callingPkg); Loading @@ -518,26 +511,47 @@ public abstract class ContentProvider implements ComponentCallbacks2 { == 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} */ protected void enforceReadPermissionInner(Uri uri, IBinder callerToken) protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); String missingPerm = null; int strongestMode = MODE_ALLOWED; if (UserHandle.isSameApp(uid, mMyUid)) { return; return MODE_ALLOWED; } if (mExported && checkUser(pid, uid, context)) { final String componentPerm = getReadPermission(); if (componentPerm != null) { if (context.checkPermission(componentPerm, pid, uid, callerToken) == PERMISSION_GRANTED) { return; final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { missingPerm = componentPerm; strongestMode = Math.max(strongestMode, mode); } } Loading @@ -551,14 +565,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 { for (PathPermission pp : pps) { final String pathPerm = pp.getReadPermission(); if (pathPerm != null && pp.match(path)) { if (context.checkPermission(pathPerm, pid, uid, callerToken) == PERMISSION_GRANTED) { return; final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { // any denied <path-permission> means we lose // default <provider> access. allowDefaultRead = false; missingPerm = pathPerm; strongestMode = Math.max(strongestMode, mode); } } } Loading @@ -566,7 +581,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { // if we passed <path-permission> checks above, and no default // <provider> permission, then allow access. if (allowDefaultRead) return; if (allowDefaultRead) return MODE_ALLOWED; } // last chance, check against any uri grants Loading @@ -575,7 +590,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 { ? maybeAddUserId(uri, callingUserId) : uri; if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, 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 Loading @@ -587,25 +608,27 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } /** {@hide} */ protected void enforceWritePermissionInner(Uri uri, IBinder callerToken) protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); String missingPerm = null; int strongestMode = MODE_ALLOWED; if (UserHandle.isSameApp(uid, mMyUid)) { return; return MODE_ALLOWED; } if (mExported && checkUser(pid, uid, context)) { final String componentPerm = getWritePermission(); if (componentPerm != null) { if (context.checkPermission(componentPerm, pid, uid, callerToken) == PERMISSION_GRANTED) { return; final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { missingPerm = componentPerm; strongestMode = Math.max(strongestMode, mode); } } Loading @@ -619,14 +642,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 { for (PathPermission pp : pps) { final String pathPerm = pp.getWritePermission(); if (pathPerm != null && pp.match(path)) { if (context.checkPermission(pathPerm, pid, uid, callerToken) == PERMISSION_GRANTED) { return; final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { // any denied <path-permission> means we lose // default <provider> access. allowDefaultWrite = false; missingPerm = pathPerm; strongestMode = Math.max(strongestMode, mode); } } } Loading @@ -634,13 +658,19 @@ public abstract class ContentProvider implements ComponentCallbacks2 { // if we passed <path-permission> checks above, and no default // <provider> permission, then allow access. if (allowDefaultWrite) return; if (allowDefaultWrite) return MODE_ALLOWED; } // last chance, check against any uri grants if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 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 Loading
core/java/android/provider/DocumentsProvider.java +3 −3 Original line number Diff line number Diff line Loading @@ -640,7 +640,7 @@ public abstract class DocumentsProvider extends ContentProvider { final Bundle out = new Bundle(); try { if (METHOD_CREATE_DOCUMENT.equals(method)) { enforceWritePermissionInner(documentUri, null); enforceWritePermissionInner(documentUri, getCallingPackage(), null); final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE); final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME); Loading @@ -654,7 +654,7 @@ public abstract class DocumentsProvider extends ContentProvider { out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri); } 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 newDocumentId = renameDocument(documentId, displayName); Loading @@ -678,7 +678,7 @@ public abstract class DocumentsProvider extends ContentProvider { } } else if (METHOD_DELETE_DOCUMENT.equals(method)) { enforceWritePermissionInner(documentUri, null); enforceWritePermissionInner(documentUri, getCallingPackage(), null); deleteDocument(documentId); // Document no longer exists, clean up any grants Loading