am 2903d6fa: am c09b6a46: Merge "Better enforcement in DocumentsProvider.call()." into klp-dev

* commit '2903d6fa19e90ad4546330431e2a26245dc0d5bc':
  Better enforcement in DocumentsProvider.call().
This commit is contained in:
Jeff Sharkey
2013-10-31 17:59:47 -07:00
committed by Android Git Automerger
2 changed files with 114 additions and 115 deletions

View File

@@ -398,67 +398,6 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
return AppOpsManager.MODE_ALLOWED;
}
private void enforceReadPermissionInner(Uri uri) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
String missingPerm = null;
if (UserHandle.isSameApp(uid, mMyUid)) {
return;
}
if (mExported) {
final String componentPerm = getReadPermission();
if (componentPerm != null) {
if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
return;
} else {
missingPerm = componentPerm;
}
}
// track if unprotected read is allowed; any denied
// <path-permission> below removes this ability
boolean allowDefaultRead = (componentPerm == null);
final PathPermission[] pps = getPathPermissions();
if (pps != null) {
final String path = uri.getPath();
for (PathPermission pp : pps) {
final String pathPerm = pp.getReadPermission();
if (pathPerm != null && pp.match(path)) {
if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
return;
} else {
// any denied <path-permission> means we lose
// default <provider> access.
allowDefaultRead = false;
missingPerm = pathPerm;
}
}
}
}
// if we passed <path-permission> checks above, and no default
// <provider> permission, then allow access.
if (allowDefaultRead) return;
}
// last chance, check against any uri grants
if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
== PERMISSION_GRANTED) {
return;
}
final String failReason = mExported
? " requires " + missingPerm + ", or grantUriPermission()"
: " requires the provider be exported, or grantUriPermission()";
throw new SecurityException("Permission Denial: reading "
+ ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
+ ", uid=" + uid + failReason);
}
private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException {
enforceWritePermissionInner(uri);
if (mWriteOp != AppOpsManager.OP_NONE) {
@@ -466,67 +405,130 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
return AppOpsManager.MODE_ALLOWED;
}
}
private void enforceWritePermissionInner(Uri uri) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
String missingPerm = null;
/** {@hide} */
protected void enforceReadPermissionInner(Uri uri) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
String missingPerm = null;
if (UserHandle.isSameApp(uid, mMyUid)) {
return;
if (UserHandle.isSameApp(uid, mMyUid)) {
return;
}
if (mExported) {
final String componentPerm = getReadPermission();
if (componentPerm != null) {
if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
return;
} else {
missingPerm = componentPerm;
}
}
if (mExported) {
final String componentPerm = getWritePermission();
if (componentPerm != null) {
if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
return;
} else {
missingPerm = componentPerm;
}
}
// track if unprotected read is allowed; any denied
// <path-permission> below removes this ability
boolean allowDefaultRead = (componentPerm == null);
// track if unprotected write is allowed; any denied
// <path-permission> below removes this ability
boolean allowDefaultWrite = (componentPerm == null);
final PathPermission[] pps = getPathPermissions();
if (pps != null) {
final String path = uri.getPath();
for (PathPermission pp : pps) {
final String pathPerm = pp.getWritePermission();
if (pathPerm != null && pp.match(path)) {
if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
return;
} else {
// any denied <path-permission> means we lose
// default <provider> access.
allowDefaultWrite = false;
missingPerm = pathPerm;
}
final PathPermission[] pps = getPathPermissions();
if (pps != null) {
final String path = uri.getPath();
for (PathPermission pp : pps) {
final String pathPerm = pp.getReadPermission();
if (pathPerm != null && pp.match(path)) {
if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
return;
} else {
// any denied <path-permission> means we lose
// default <provider> access.
allowDefaultRead = false;
missingPerm = pathPerm;
}
}
}
// if we passed <path-permission> checks above, and no default
// <provider> permission, then allow access.
if (allowDefaultWrite) return;
}
// last chance, check against any uri grants
if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
== PERMISSION_GRANTED) {
return;
}
final String failReason = mExported
? " requires " + missingPerm + ", or grantUriPermission()"
: " requires the provider be exported, or grantUriPermission()";
throw new SecurityException("Permission Denial: writing "
+ ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
+ ", uid=" + uid + failReason);
// if we passed <path-permission> checks above, and no default
// <provider> permission, then allow access.
if (allowDefaultRead) return;
}
// last chance, check against any uri grants
if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
== PERMISSION_GRANTED) {
return;
}
final String failReason = mExported
? " requires " + missingPerm + ", or grantUriPermission()"
: " requires the provider be exported, or grantUriPermission()";
throw new SecurityException("Permission Denial: reading "
+ ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
+ ", uid=" + uid + failReason);
}
/** {@hide} */
protected void enforceWritePermissionInner(Uri uri) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
String missingPerm = null;
if (UserHandle.isSameApp(uid, mMyUid)) {
return;
}
if (mExported) {
final String componentPerm = getWritePermission();
if (componentPerm != null) {
if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
return;
} else {
missingPerm = componentPerm;
}
}
// track if unprotected write is allowed; any denied
// <path-permission> below removes this ability
boolean allowDefaultWrite = (componentPerm == null);
final PathPermission[] pps = getPathPermissions();
if (pps != null) {
final String path = uri.getPath();
for (PathPermission pp : pps) {
final String pathPerm = pp.getWritePermission();
if (pathPerm != null && pp.match(path)) {
if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
return;
} else {
// any denied <path-permission> means we lose
// default <provider> access.
allowDefaultWrite = false;
missingPerm = pathPerm;
}
}
}
}
// if we passed <path-permission> checks above, and no default
// <provider> permission, then allow access.
if (allowDefaultWrite) return;
}
// last chance, check against any uri grants
if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
== PERMISSION_GRANTED) {
return;
}
final String failReason = mExported
? " requires " + missingPerm + ", or grantUriPermission()"
: " requires the provider be exported, or grantUriPermission()";
throw new SecurityException("Permission Denial: writing "
+ ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
+ ", uid=" + uid + failReason);
}
/**

View File

@@ -512,10 +512,7 @@ public abstract class DocumentsProvider extends ContentProvider {
final boolean callerHasManage =
context.checkCallingOrSelfPermission(android.Manifest.permission.MANAGE_DOCUMENTS)
== PackageManager.PERMISSION_GRANTED;
if (!callerHasManage) {
getContext().enforceCallingOrSelfUriPermission(
documentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, method);
}
enforceWritePermissionInner(documentUri);
final Bundle out = new Bundle();
try {