Merge "Recover shady content:// paths." into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
7402d7611c
@@ -54,6 +54,7 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Content providers are one of the primary building blocks of Android applications, providing
|
||||
@@ -209,7 +210,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
@Override
|
||||
public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
|
||||
@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||
// The caller has no access to the data, so return an empty cursor with
|
||||
@@ -248,14 +249,14 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
return ContentProvider.this.getType(uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
int userId = getUserIdFromUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||
@@ -271,7 +272,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
|
||||
@Override
|
||||
public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||
return 0;
|
||||
@@ -293,11 +294,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
for (int i = 0; i < numOperations; i++) {
|
||||
ContentProviderOperation operation = operations.get(i);
|
||||
Uri uri = operation.getUri();
|
||||
validateIncomingUri(uri);
|
||||
userIds[i] = getUserIdFromUri(uri);
|
||||
if (userIds[i] != UserHandle.USER_CURRENT) {
|
||||
// Removing the user id from the uri.
|
||||
operation = new ContentProviderOperation(operation, true);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
// Rebuild operation if we changed the Uri above
|
||||
if (!Objects.equals(operation.getUri(), uri)) {
|
||||
operation = new ContentProviderOperation(operation, uri);
|
||||
operations.set(i, operation);
|
||||
}
|
||||
if (operation.isReadOperation()) {
|
||||
@@ -332,7 +334,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
|
||||
@Override
|
||||
public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||
return 0;
|
||||
@@ -348,7 +350,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
@Override
|
||||
public int update(String callingPkg, Uri uri, ContentValues values, String selection,
|
||||
String[] selectionArgs) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||
return 0;
|
||||
@@ -365,7 +367,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
public ParcelFileDescriptor openFile(
|
||||
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal,
|
||||
IBinder callerToken) throws FileNotFoundException {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
enforceFilePermission(callingPkg, uri, mode, callerToken);
|
||||
final String original = setCallingPackage(callingPkg);
|
||||
@@ -381,7 +383,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
public AssetFileDescriptor openAssetFile(
|
||||
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
|
||||
throws FileNotFoundException {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
enforceFilePermission(callingPkg, uri, mode, null);
|
||||
final String original = setCallingPackage(callingPkg);
|
||||
@@ -407,7 +409,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
|
||||
@Override
|
||||
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
|
||||
}
|
||||
@@ -416,7 +418,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
|
||||
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
|
||||
Bundle.setDefusable(opts, true);
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = maybeGetUriWithoutUserId(uri);
|
||||
enforceFilePermission(callingPkg, uri, "r", null);
|
||||
final String original = setCallingPackage(callingPkg);
|
||||
@@ -435,7 +437,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
|
||||
@Override
|
||||
public Uri canonicalize(String callingPkg, Uri uri) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
int userId = getUserIdFromUri(uri);
|
||||
uri = getUriWithoutUserId(uri);
|
||||
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||
@@ -451,7 +453,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
|
||||
@Override
|
||||
public Uri uncanonicalize(String callingPkg, Uri uri) {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
int userId = getUserIdFromUri(uri);
|
||||
uri = getUriWithoutUserId(uri);
|
||||
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||
@@ -468,7 +470,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
@Override
|
||||
public boolean refresh(String callingPkg, Uri uri, Bundle args,
|
||||
ICancellationSignal cancellationSignal) throws RemoteException {
|
||||
validateIncomingUri(uri);
|
||||
uri = validateIncomingUri(uri);
|
||||
uri = getUriWithoutUserId(uri);
|
||||
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||
return false;
|
||||
@@ -1902,7 +1904,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
*/
|
||||
if (mContext == null) {
|
||||
mContext = context;
|
||||
if (context != null) {
|
||||
if (context != null && mTransport != null) {
|
||||
mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
|
||||
Context.APP_OPS_SERVICE);
|
||||
}
|
||||
@@ -2011,7 +2013,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
private void validateIncomingUri(Uri uri) throws SecurityException {
|
||||
public Uri validateIncomingUri(Uri uri) throws SecurityException {
|
||||
String auth = uri.getAuthority();
|
||||
if (!mSingleUser) {
|
||||
int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
|
||||
@@ -2030,6 +2032,19 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
||||
}
|
||||
throw new SecurityException(message);
|
||||
}
|
||||
|
||||
// Normalize the path by removing any empty path segments, which can be
|
||||
// a source of security issues.
|
||||
final String encodedPath = uri.getEncodedPath();
|
||||
if (encodedPath != null && encodedPath.indexOf("//") != -1) {
|
||||
final Uri normalized = uri.buildUpon()
|
||||
.encodedPath(encodedPath.replaceAll("//+", "/")).build();
|
||||
Log.w(TAG, "Normalized " + uri + " to " + normalized
|
||||
+ " to avoid possible security issues");
|
||||
return normalized;
|
||||
} else {
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
|
||||
@@ -94,13 +94,9 @@ public class ContentProviderOperation implements Parcelable {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) {
|
||||
public ContentProviderOperation(ContentProviderOperation cpo, Uri withUri) {
|
||||
mType = cpo.mType;
|
||||
if (removeUserIdFromUri) {
|
||||
mUri = ContentProvider.getUriWithoutUserId(cpo.mUri);
|
||||
} else {
|
||||
mUri = cpo.mUri;
|
||||
}
|
||||
mUri = withUri;
|
||||
mValues = cpo.mValues;
|
||||
mSelection = cpo.mSelection;
|
||||
mSelectionArgs = cpo.mSelectionArgs;
|
||||
@@ -110,14 +106,6 @@ public class ContentProviderOperation implements Parcelable {
|
||||
mYieldAllowed = cpo.mYieldAllowed;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public ContentProviderOperation getWithoutUserIdInUri() {
|
||||
if (ContentProvider.uriHasUserId(mUri)) {
|
||||
return new ContentProviderOperation(this, true);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mType);
|
||||
Uri.writeToParcel(dest, mUri);
|
||||
|
||||
Reference in New Issue
Block a user