From 4a546f5f6e22747304a07ab6892aa318447b5fe7 Mon Sep 17 00:00:00 2001 From: Marc Blank Date: Wed, 11 Aug 2010 17:31:45 -0700 Subject: [PATCH] DO NOT MERGE: Backport AttachmentProvider security fix * Apps trying to open attachments using AttachmentProvider were seeing SecurityExceptions due to the fact that internal calls from AttachmentProvider to EmailProvider didn't have their calling identity saved/restored. * Updated provider calls so that these calls use the Email process' identity. * Backport of Ifb71ad834530c6232728e1aad31439991f8ed379, fixing 2908737 Bug: 3121146 Change-Id: Ifa3a0ca8d3e34733c937d7f8c60f068984e1f4f2 --- .../email/provider/AttachmentProvider.java | 232 ++++++++++-------- 1 file changed, 124 insertions(+), 108 deletions(-) diff --git a/src/com/android/email/provider/AttachmentProvider.java b/src/com/android/email/provider/AttachmentProvider.java index 2b3722a6e..0860c562a 100644 --- a/src/com/android/email/provider/AttachmentProvider.java +++ b/src/com/android/email/provider/AttachmentProvider.java @@ -33,6 +33,7 @@ import android.database.MatrixCursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; +import android.os.Binder; import android.os.ParcelFileDescriptor; import android.text.TextUtils; import android.util.Log; @@ -151,27 +152,31 @@ public class AttachmentProvider extends ContentProvider { */ @Override public String getType(Uri uri) { - List segments = uri.getPathSegments(); - String accountId = segments.get(0); - String id = segments.get(1); - String format = segments.get(2); - if (FORMAT_THUMBNAIL.equals(format)) { - return "image/png"; - } else { - uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id)); - Cursor c = getContext().getContentResolver().query(uri, MIME_TYPE_PROJECTION, - null, null, null); - try { - if (c.moveToFirst()) { - String mimeType = c.getString(MIME_TYPE_COLUMN_MIME_TYPE); - String fileName = c.getString(MIME_TYPE_COLUMN_FILENAME); - mimeType = inferMimeType(fileName, mimeType); - return mimeType; + long callingId = Binder.clearCallingIdentity(); + try { + List segments = uri.getPathSegments(); + String id = segments.get(1); + String format = segments.get(2); + if (FORMAT_THUMBNAIL.equals(format)) { + return "image/png"; + } else { + uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id)); + Cursor c = getContext().getContentResolver().query(uri, MIME_TYPE_PROJECTION, + null, null, null); + try { + if (c.moveToFirst()) { + String mimeType = c.getString(MIME_TYPE_COLUMN_MIME_TYPE); + String fileName = c.getString(MIME_TYPE_COLUMN_FILENAME); + mimeType = inferMimeType(fileName, mimeType); + return mimeType; + } + } finally { + c.close(); } - } finally { - c.close(); + return null; } - return null; + } finally { + Binder.restoreCallingIdentity(callingId); } } @@ -230,58 +235,64 @@ public class AttachmentProvider extends ContentProvider { */ @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - List segments = uri.getPathSegments(); - String accountId = segments.get(0); - String id = segments.get(1); - String format = segments.get(2); - if (FORMAT_THUMBNAIL.equals(format)) { - int width = Integer.parseInt(segments.get(3)); - int height = Integer.parseInt(segments.get(4)); - String filename = "thmb_" + accountId + "_" + id; - File dir = getContext().getCacheDir(); - File file = new File(dir, filename); - if (!file.exists()) { - Uri attachmentUri = getAttachmentUri(Long.parseLong(accountId), Long.parseLong(id)); - Cursor c = query(attachmentUri, - new String[] { AttachmentProviderColumns.DATA }, null, null, null); - if (c != null) { + long callingId = Binder.clearCallingIdentity(); + try { + List segments = uri.getPathSegments(); + String accountId = segments.get(0); + String id = segments.get(1); + String format = segments.get(2); + if (FORMAT_THUMBNAIL.equals(format)) { + int width = Integer.parseInt(segments.get(3)); + int height = Integer.parseInt(segments.get(4)); + String filename = "thmb_" + accountId + "_" + id; + File dir = getContext().getCacheDir(); + File file = new File(dir, filename); + if (!file.exists()) { + Uri attachmentUri = + getAttachmentUri(Long.parseLong(accountId), Long.parseLong(id)); + Cursor c = query(attachmentUri, + new String[] { AttachmentProviderColumns.DATA }, null, null, null); + if (c != null) { + try { + if (c.moveToFirst()) { + attachmentUri = Uri.parse(c.getString(0)); + } else { + return null; + } + } finally { + c.close(); + } + } + String type = getContext().getContentResolver().getType(attachmentUri); try { - if (c.moveToFirst()) { - attachmentUri = Uri.parse(c.getString(0)); - } else { + InputStream in = + getContext().getContentResolver().openInputStream(attachmentUri); + Bitmap thumbnail = createThumbnail(type, in); + if (thumbnail == null) { return null; } - } finally { - c.close(); - } - } - String type = getContext().getContentResolver().getType(attachmentUri); - try { - InputStream in = - getContext().getContentResolver().openInputStream(attachmentUri); - Bitmap thumbnail = createThumbnail(type, in); - if (thumbnail == null) { + thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true); + FileOutputStream out = new FileOutputStream(file); + thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out); + out.close(); + in.close(); + } catch (IOException ioe) { + Log.d(Email.LOG_TAG, "openFile/thumbnail failed with " + ioe.getMessage()); + return null; + } catch (OutOfMemoryError oome) { + Log.d(Email.LOG_TAG, "openFile/thumbnail failed with " + oome.getMessage()); return null; } - thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true); - FileOutputStream out = new FileOutputStream(file); - thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out); - out.close(); - in.close(); - } catch (IOException ioe) { - Log.d(Email.LOG_TAG, "openFile/thumbnail failed with " + ioe.getMessage()); - return null; - } catch (OutOfMemoryError oome) { - Log.d(Email.LOG_TAG, "openFile/thumbnail failed with " + oome.getMessage()); - return null; + } + return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); } + else { + return ParcelFileDescriptor.open( + new File(getContext().getDatabasePath(accountId + ".db_att"), id), + ParcelFileDescriptor.MODE_READ_ONLY); } - return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); - } - else { - return ParcelFileDescriptor.open( - new File(getContext().getDatabasePath(accountId + ".db_att"), id), - ParcelFileDescriptor.MODE_READ_ONLY); + } finally { + Binder.restoreCallingIdentity(callingId); } } @@ -305,56 +316,61 @@ public class AttachmentProvider extends ContentProvider { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - if (projection == null) { - projection = - new String[] { - AttachmentProviderColumns._ID, - AttachmentProviderColumns.DATA, - }; - } - - List segments = uri.getPathSegments(); - String accountId = segments.get(0); - String id = segments.get(1); - String format = segments.get(2); - String name = null; - int size = -1; - String contentUri = null; - - uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id)); - Cursor c = getContext().getContentResolver().query(uri, PROJECTION_QUERY, - null, null, null); + long callingId = Binder.clearCallingIdentity(); try { - if (c.moveToFirst()) { - name = c.getString(0); - size = c.getInt(1); - contentUri = c.getString(2); - } else { - return null; + if (projection == null) { + projection = + new String[] { + AttachmentProviderColumns._ID, + AttachmentProviderColumns.DATA, + }; } - } finally { - c.close(); - } - MatrixCursor ret = new MatrixCursor(projection); - Object[] values = new Object[projection.length]; - for (int i = 0, count = projection.length; i < count; i++) { - String column = projection[i]; - if (AttachmentProviderColumns._ID.equals(column)) { - values[i] = id; + List segments = uri.getPathSegments(); + String accountId = segments.get(0); + String id = segments.get(1); + String format = segments.get(2); + String name = null; + int size = -1; + String contentUri = null; + + uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id)); + Cursor c = getContext().getContentResolver().query(uri, PROJECTION_QUERY, + null, null, null); + try { + if (c.moveToFirst()) { + name = c.getString(0); + size = c.getInt(1); + contentUri = c.getString(2); + } else { + return null; + } + } finally { + c.close(); } - else if (AttachmentProviderColumns.DATA.equals(column)) { - values[i] = contentUri; - } - else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column)) { - values[i] = name; - } - else if (AttachmentProviderColumns.SIZE.equals(column)) { - values[i] = size; + + MatrixCursor ret = new MatrixCursor(projection); + Object[] values = new Object[projection.length]; + for (int i = 0, count = projection.length; i < count; i++) { + String column = projection[i]; + if (AttachmentProviderColumns._ID.equals(column)) { + values[i] = id; + } + else if (AttachmentProviderColumns.DATA.equals(column)) { + values[i] = contentUri; + } + else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column)) { + values[i] = name; + } + else if (AttachmentProviderColumns.SIZE.equals(column)) { + values[i] = size; + } } + ret.addRow(values); + return ret; + } finally { + Binder.restoreCallingIdentity(callingId); } - ret.addRow(values); - return ret; } @Override