[automerger] RESTRICT AUTOMERGE: Recover shady content:// paths. am: 301d17e4dd
Change-Id: I80ac911a166e12eedf77518436808d4f3ede872c
This commit is contained in:
@@ -53,6 +53,7 @@ import java.io.IOException;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Content providers are one of the primary building blocks of Android applications, providing
|
* Content providers are one of the primary building blocks of Android applications, providing
|
||||||
@@ -207,7 +208,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
public Cursor query(String callingPkg, Uri uri, String[] projection,
|
public Cursor query(String callingPkg, Uri uri, String[] projection,
|
||||||
String selection, String[] selectionArgs, String sortOrder,
|
String selection, String[] selectionArgs, String sortOrder,
|
||||||
ICancellationSignal cancellationSignal) {
|
ICancellationSignal cancellationSignal) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||||
// The caller has no access to the data, so return an empty cursor with
|
// The caller has no access to the data, so return an empty cursor with
|
||||||
@@ -246,14 +247,14 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType(Uri uri) {
|
public String getType(Uri uri) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
return ContentProvider.this.getType(uri);
|
return ContentProvider.this.getType(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
|
public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
int userId = getUserIdFromUri(uri);
|
int userId = getUserIdFromUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||||
@@ -269,7 +270,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
|
public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -291,11 +292,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
for (int i = 0; i < numOperations; i++) {
|
for (int i = 0; i < numOperations; i++) {
|
||||||
ContentProviderOperation operation = operations.get(i);
|
ContentProviderOperation operation = operations.get(i);
|
||||||
Uri uri = operation.getUri();
|
Uri uri = operation.getUri();
|
||||||
validateIncomingUri(uri);
|
|
||||||
userIds[i] = getUserIdFromUri(uri);
|
userIds[i] = getUserIdFromUri(uri);
|
||||||
if (userIds[i] != UserHandle.USER_CURRENT) {
|
uri = validateIncomingUri(uri);
|
||||||
// Removing the user id from the uri.
|
uri = getUriWithoutUserId(uri);
|
||||||
operation = new ContentProviderOperation(operation, true);
|
// Rebuild operation if we changed the Uri above
|
||||||
|
if (!Objects.equals(operation.getUri(), uri)) {
|
||||||
|
operation = new ContentProviderOperation(operation, uri);
|
||||||
operations.set(i, operation);
|
operations.set(i, operation);
|
||||||
}
|
}
|
||||||
if (operation.isReadOperation()) {
|
if (operation.isReadOperation()) {
|
||||||
@@ -330,7 +332,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
|
public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -346,7 +348,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
@Override
|
@Override
|
||||||
public int update(String callingPkg, Uri uri, ContentValues values, String selection,
|
public int update(String callingPkg, Uri uri, ContentValues values, String selection,
|
||||||
String[] selectionArgs) {
|
String[] selectionArgs) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -363,7 +365,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
public ParcelFileDescriptor openFile(
|
public ParcelFileDescriptor openFile(
|
||||||
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal,
|
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal,
|
||||||
IBinder callerToken) throws FileNotFoundException {
|
IBinder callerToken) throws FileNotFoundException {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
enforceFilePermission(callingPkg, uri, mode, callerToken);
|
enforceFilePermission(callingPkg, uri, mode, callerToken);
|
||||||
final String original = setCallingPackage(callingPkg);
|
final String original = setCallingPackage(callingPkg);
|
||||||
@@ -379,7 +381,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
public AssetFileDescriptor openAssetFile(
|
public AssetFileDescriptor openAssetFile(
|
||||||
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
|
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
|
||||||
throws FileNotFoundException {
|
throws FileNotFoundException {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
enforceFilePermission(callingPkg, uri, mode, null);
|
enforceFilePermission(callingPkg, uri, mode, null);
|
||||||
final String original = setCallingPackage(callingPkg);
|
final String original = setCallingPackage(callingPkg);
|
||||||
@@ -405,7 +407,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
|
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
|
return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
|
||||||
}
|
}
|
||||||
@@ -414,7 +416,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
|
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
|
||||||
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
|
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
|
||||||
Bundle.setDefusable(opts, true);
|
Bundle.setDefusable(opts, true);
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
enforceFilePermission(callingPkg, uri, "r", null);
|
enforceFilePermission(callingPkg, uri, "r", null);
|
||||||
final String original = setCallingPackage(callingPkg);
|
final String original = setCallingPackage(callingPkg);
|
||||||
@@ -433,7 +435,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Uri canonicalize(String callingPkg, Uri uri) {
|
public Uri canonicalize(String callingPkg, Uri uri) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
int userId = getUserIdFromUri(uri);
|
int userId = getUserIdFromUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||||
@@ -449,7 +451,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Uri uncanonicalize(String callingPkg, Uri uri) {
|
public Uri uncanonicalize(String callingPkg, Uri uri) {
|
||||||
validateIncomingUri(uri);
|
uri = validateIncomingUri(uri);
|
||||||
int userId = getUserIdFromUri(uri);
|
int userId = getUserIdFromUri(uri);
|
||||||
uri = getUriWithoutUserId(uri);
|
uri = getUriWithoutUserId(uri);
|
||||||
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
|
||||||
@@ -1735,7 +1737,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
*/
|
*/
|
||||||
if (mContext == null) {
|
if (mContext == null) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
if (context != null) {
|
if (context != null && mTransport != null) {
|
||||||
mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
|
mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
|
||||||
Context.APP_OPS_SERVICE);
|
Context.APP_OPS_SERVICE);
|
||||||
}
|
}
|
||||||
@@ -1844,7 +1846,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
private void validateIncomingUri(Uri uri) throws SecurityException {
|
public Uri validateIncomingUri(Uri uri) throws SecurityException {
|
||||||
String auth = uri.getAuthority();
|
String auth = uri.getAuthority();
|
||||||
int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
|
int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
|
||||||
if (userId != UserHandle.USER_CURRENT && userId != mContext.getUserId()) {
|
if (userId != UserHandle.USER_CURRENT && userId != mContext.getUserId()) {
|
||||||
@@ -1861,6 +1863,19 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
|
|||||||
}
|
}
|
||||||
throw new SecurityException(message);
|
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 */
|
/** @hide */
|
||||||
|
|||||||
@@ -94,13 +94,9 @@ public class ContentProviderOperation implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) {
|
public ContentProviderOperation(ContentProviderOperation cpo, Uri withUri) {
|
||||||
mType = cpo.mType;
|
mType = cpo.mType;
|
||||||
if (removeUserIdFromUri) {
|
mUri = withUri;
|
||||||
mUri = ContentProvider.getUriWithoutUserId(cpo.mUri);
|
|
||||||
} else {
|
|
||||||
mUri = cpo.mUri;
|
|
||||||
}
|
|
||||||
mValues = cpo.mValues;
|
mValues = cpo.mValues;
|
||||||
mSelection = cpo.mSelection;
|
mSelection = cpo.mSelection;
|
||||||
mSelectionArgs = cpo.mSelectionArgs;
|
mSelectionArgs = cpo.mSelectionArgs;
|
||||||
@@ -110,14 +106,6 @@ public class ContentProviderOperation implements Parcelable {
|
|||||||
mYieldAllowed = cpo.mYieldAllowed;
|
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) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeInt(mType);
|
dest.writeInt(mType);
|
||||||
Uri.writeToParcel(dest, mUri);
|
Uri.writeToParcel(dest, mUri);
|
||||||
|
|||||||
Reference in New Issue
Block a user