diff options
author | Jeff Sharkey <jsharkey@android.com> | 2013-04-03 23:28:07 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-04-03 23:28:07 +0000 |
commit | 0f8e8b03ebb35040c299079adc1c351f37ce4885 (patch) | |
tree | 19158f23cbd5b9dff30b7f6bedea8bba81f9ecb7 | |
parent | 0d17aaa543f393c6c792f0b0d8ec5cb38ff1f71e (diff) | |
parent | a14acd20b8d563319ea1a5974dca0e9a29f0aaef (diff) | |
download | frameworks_base-0f8e8b03ebb35040c299079adc1c351f37ce4885.zip frameworks_base-0f8e8b03ebb35040c299079adc1c351f37ce4885.tar.gz frameworks_base-0f8e8b03ebb35040c299079adc1c351f37ce4885.tar.bz2 |
Merge "Warn when exposing file:// Uris beyond a process." into jb-mr2-dev
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 16 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 37 | ||||
-rw-r--r-- | core/java/android/app/Instrumentation.java | 9 | ||||
-rw-r--r-- | core/java/android/app/NotificationManager.java | 7 | ||||
-rw-r--r-- | core/java/android/app/PendingIntent.java | 14 | ||||
-rw-r--r-- | core/java/android/content/BroadcastReceiver.java | 2 | ||||
-rw-r--r-- | core/java/android/content/ClipData.java | 19 | ||||
-rw-r--r-- | core/java/android/content/ClipboardManager.java | 4 | ||||
-rw-r--r-- | core/java/android/content/Intent.java | 27 | ||||
-rw-r--r-- | core/java/android/net/Uri.java | 13 | ||||
-rw-r--r-- | core/java/android/os/StrictMode.java | 35 | ||||
-rw-r--r-- | core/java/android/widget/RemoteViews.java | 10 |
13 files changed, 155 insertions, 39 deletions
diff --git a/api/current.txt b/api/current.txt index e001e1a..b9c67c4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16940,6 +16940,7 @@ package android.os { method public android.os.StrictMode.VmPolicy build(); method public android.os.StrictMode.VmPolicy.Builder detectActivityLeaks(); method public android.os.StrictMode.VmPolicy.Builder detectAll(); + method public android.os.StrictMode.VmPolicy.Builder detectFileUriExposure(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects(); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 87c2d8c..31074e2 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3513,7 +3513,8 @@ public class Activity extends ContextThemeWrapper try { String resolvedType = null; if (fillInIntent != null) { - fillInIntent.setAllowFds(false); + fillInIntent.migrateExtraStreamToClipData(); + fillInIntent.prepareToLeaveProcess(); resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver()); } int result = ActivityManagerNative.getDefault() @@ -3738,7 +3739,8 @@ public class Activity extends ContextThemeWrapper if (mParent == null) { int result = ActivityManager.START_RETURN_INTENT_TO_CALLER; try { - intent.setAllowFds(false); + intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); result = ActivityManagerNative.getDefault() .startActivity(mMainThread.getApplicationThread(), getBasePackageName(), intent, intent.resolveTypeIfNeeded(getContentResolver()), @@ -3808,7 +3810,8 @@ public class Activity extends ContextThemeWrapper public boolean startNextMatchingActivity(Intent intent, Bundle options) { if (mParent == null) { try { - intent.setAllowFds(false); + intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); return ActivityManagerNative.getDefault() .startNextMatchingActivity(mToken, intent, options); } catch (RemoteException e) { @@ -4162,7 +4165,7 @@ public class Activity extends ContextThemeWrapper if (false) Log.v(TAG, "Finishing self: token=" + mToken); try { if (resultData != null) { - resultData.setAllowFds(false); + resultData.prepareToLeaveProcess(); } if (ActivityManagerNative.getDefault() .finishActivity(mToken, resultCode, resultData)) { @@ -4314,7 +4317,7 @@ public class Activity extends ContextThemeWrapper int flags) { String packageName = getPackageName(); try { - data.setAllowFds(false); + data.prepareToLeaveProcess(); IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName, @@ -4993,9 +4996,10 @@ public class Activity extends ContextThemeWrapper resultData = mResultData; } if (resultData != null) { - resultData.setAllowFds(false); + resultData.prepareToLeaveProcess(); } try { + upIntent.prepareToLeaveProcess(); return ActivityManagerNative.getDefault().navigateUpTo(mToken, upIntent, resultCode, resultData); } catch (RemoteException e) { diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 459e49c..9bf8830 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1020,7 +1020,8 @@ class ContextImpl extends Context { try { String resolvedType = null; if (fillInIntent != null) { - fillInIntent.setAllowFds(false); + fillInIntent.migrateExtraStreamToClipData(); + fillInIntent.prepareToLeaveProcess(); resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver()); } int result = ActivityManagerNative.getDefault() @@ -1040,7 +1041,7 @@ class ContextImpl extends Context { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false, @@ -1054,7 +1055,7 @@ class ContextImpl extends Context { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, @@ -1068,7 +1069,7 @@ class ContextImpl extends Context { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermission, appOp, false, false, @@ -1083,7 +1084,7 @@ class ContextImpl extends Context { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, true, false, @@ -1126,7 +1127,7 @@ class ContextImpl extends Context { } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermission, appOp, @@ -1139,7 +1140,7 @@ class ContextImpl extends Context { public void sendBroadcastAsUser(Intent intent, UserHandle user) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false, user.getIdentifier()); @@ -1152,7 +1153,7 @@ class ContextImpl extends Context { String receiverPermission) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, false, false, @@ -1184,7 +1185,7 @@ class ContextImpl extends Context { } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermission, @@ -1198,7 +1199,7 @@ class ContextImpl extends Context { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, true, @@ -1232,7 +1233,7 @@ class ContextImpl extends Context { } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, null, @@ -1249,7 +1250,7 @@ class ContextImpl extends Context { intent.setDataAndType(intent.getData(), resolvedType); } try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().unbroadcastIntent( mMainThread.getApplicationThread(), intent, getUserId()); } catch (RemoteException e) { @@ -1260,7 +1261,7 @@ class ContextImpl extends Context { public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, true, user.getIdentifier()); @@ -1292,7 +1293,7 @@ class ContextImpl extends Context { } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, null, @@ -1309,7 +1310,7 @@ class ContextImpl extends Context { intent.setDataAndType(intent.getData(), resolvedType); } try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().unbroadcastIntent( mMainThread.getApplicationThread(), intent, user.getIdentifier()); } catch (RemoteException e) { @@ -1393,7 +1394,7 @@ class ContextImpl extends Context { @Override public ComponentName startServiceAsUser(Intent service, UserHandle user) { try { - service.setAllowFds(false); + service.prepareToLeaveProcess(); ComponentName cn = ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); @@ -1417,7 +1418,7 @@ class ContextImpl extends Context { @Override public boolean stopServiceAsUser(Intent service, UserHandle user) { try { - service.setAllowFds(false); + service.prepareToLeaveProcess(); int res = ActivityManagerNative.getDefault().stopService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); @@ -1459,7 +1460,7 @@ class ContextImpl extends Context { < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { flags |= BIND_WAIVE_PRIORITY; } - service.setAllowFds(false); + service.prepareToLeaveProcess(); int res = ActivityManagerNative.getDefault().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index e7bf305..e0dfb25 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1410,8 +1410,8 @@ public class Instrumentation { } } try { - intent.setAllowFds(false); intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), @@ -1467,7 +1467,8 @@ public class Instrumentation { try { String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { - intents[i].setAllowFds(false); + intents[i].migrateExtraStreamToClipData(); + intents[i].prepareToLeaveProcess(); resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver()); } int result = ActivityManagerNative.getDefault() @@ -1526,8 +1527,8 @@ public class Instrumentation { } } try { - intent.setAllowFds(false); intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), @@ -1586,8 +1587,8 @@ public class Instrumentation { } } try { - intent.setAllowFds(false); intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); int result = ActivityManagerNative.getDefault() .startActivityAsUser(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 5e69128..dbafc78 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -21,6 +21,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.StrictMode; import android.os.UserHandle; import android.util.Log; @@ -126,6 +127,9 @@ public class NotificationManager String pkg = mContext.getPackageName(); if (notification.sound != null) { notification.sound = notification.sound.getCanonicalUri(); + if (StrictMode.vmFileUriExposureEnabled()) { + notification.sound.checkFileUriExposed("Notification.sound"); + } } if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); try { @@ -148,6 +152,9 @@ public class NotificationManager String pkg = mContext.getPackageName(); if (notification.sound != null) { notification.sound = notification.sound.getCanonicalUri(); + if (StrictMode.vmFileUriExposureEnabled()) { + notification.sound.checkFileUriExposed("Notification.sound"); + } } if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); try { diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 20114cc..25c790f 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -260,8 +260,8 @@ public final class PendingIntent implements Parcelable { String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; try { - intent.setAllowFds(false); intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, packageName, @@ -285,8 +285,8 @@ public final class PendingIntent implements Parcelable { String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; try { - intent.setAllowFds(false); intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, packageName, @@ -401,7 +401,8 @@ public final class PendingIntent implements Parcelable { String packageName = context.getPackageName(); String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { - intents[i].setAllowFds(false); + intents[i].migrateExtraStreamToClipData(); + intents[i].prepareToLeaveProcess(); resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); } try { @@ -426,7 +427,8 @@ public final class PendingIntent implements Parcelable { String packageName = context.getPackageName(); String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { - intents[i].setAllowFds(false); + intents[i].migrateExtraStreamToClipData(); + intents[i].prepareToLeaveProcess(); resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); } try { @@ -482,7 +484,7 @@ public final class PendingIntent implements Parcelable { String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_BROADCAST, packageName, @@ -526,7 +528,7 @@ public final class PendingIntent implements Parcelable { String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; try { - intent.setAllowFds(false); + intent.prepareToLeaveProcess(); IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_SERVICE, packageName, diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java index 4f42d50..9a32fdf 100644 --- a/core/java/android/content/BroadcastReceiver.java +++ b/core/java/android/content/BroadcastReceiver.java @@ -520,7 +520,7 @@ public abstract class BroadcastReceiver { IActivityManager am = ActivityManagerNative.getDefault(); IBinder binder = null; try { - service.setAllowFds(false); + service.prepareToLeaveProcess(); binder = am.peekService(service, service.resolveTypeIfNeeded( myContext.getContentResolver())); } catch (RemoteException e) { diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index 88f1a3d..50c4fed 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -21,6 +21,7 @@ import android.graphics.Bitmap; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; +import android.os.StrictMode; import android.text.Html; import android.text.Spannable; import android.text.SpannableStringBuilder; @@ -790,6 +791,24 @@ public class ClipData implements Parcelable { return mItems.get(index); } + /** + * Prepare this {@link ClipData} to leave an app process. + * + * @hide + */ + public void prepareToLeaveProcess() { + final int size = mItems.size(); + for (int i = 0; i < size; i++) { + final Item item = mItems.get(i); + if (item.mIntent != null) { + item.mIntent.prepareToLeaveProcess(); + } + if (item.mUri != null && StrictMode.vmFileUriExposureEnabled()) { + item.mUri.checkFileUriExposed("ClipData.Item.getUri()"); + } + } + } + @Override public String toString() { StringBuilder b = new StringBuilder(128); diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java index 88a4229..69f9d4a 100644 --- a/core/java/android/content/ClipboardManager.java +++ b/core/java/android/content/ClipboardManager.java @@ -22,6 +22,7 @@ import android.os.RemoteException; import android.os.Handler; import android.os.IBinder; import android.os.ServiceManager; +import android.os.StrictMode; import android.util.Log; import java.util.ArrayList; @@ -118,6 +119,9 @@ public class ClipboardManager extends android.text.ClipboardManager { */ public void setPrimaryClip(ClipData clip) { try { + if (clip != null) { + clip.prepareToLeaveProcess(); + } getService().setPrimaryClip(clip, mContext.getBasePackageName()); } catch (RemoteException e) { } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index c9b9a1a..97ad7dd 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -32,6 +32,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; +import android.os.StrictMode; import android.util.AttributeSet; import android.util.Log; @@ -6966,6 +6967,32 @@ public class Intent implements Parcelable, Cloneable { } /** + * Prepare this {@link Intent} to leave an app process. + * + * @hide + */ + public void prepareToLeaveProcess() { + setAllowFds(false); + + if (mSelector != null) { + mSelector.prepareToLeaveProcess(); + } + if (mClipData != null) { + mClipData.prepareToLeaveProcess(); + } + + if (mData != null && StrictMode.vmFileUriExposureEnabled()) { + // There are several ACTION_MEDIA_* broadcasts that send file:// + // Uris, so only check common actions. + if (ACTION_VIEW.equals(mAction) || + ACTION_EDIT.equals(mAction) || + ACTION_ATTACH_DATA.equals(mAction)) { + mData.checkFileUriExposed("Intent.getData()"); + } + } + } + + /** * Migrate any {@link #EXTRA_STREAM} in {@link #ACTION_SEND} and * {@link #ACTION_SEND_MULTIPLE} to {@link ClipData}. Also inspects nested * intents in {@link #ACTION_CHOOSER}. diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index cc6903d..4b022d9 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -20,6 +20,7 @@ import android.os.Environment; import android.os.Parcel; import android.os.Parcelable; import android.os.Environment.UserEnvironment; +import android.os.StrictMode; import android.util.Log; import java.io.File; import java.io.IOException; @@ -2326,4 +2327,16 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { return this; } } + + /** + * If this is a {@code file://} Uri, it will be reported to + * {@link StrictMode}. + * + * @hide + */ + public void checkFileUriExposed(String location) { + if ("file".equals(getScheme())) { + StrictMode.onFileUriExposed(location); + } + } } diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index f682abe..d2943ab 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -203,10 +203,15 @@ public final class StrictMode { */ public static final int DETECT_VM_REGISTRATION_LEAKS = 0x2000; // for VmPolicy + /** + * @hide + */ + private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x4000; // for VmPolicy + private static final int ALL_VM_DETECT_BITS = DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS | - DETECT_VM_REGISTRATION_LEAKS; + DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE; /** * @hide @@ -628,7 +633,8 @@ public final class StrictMode { */ public Builder detectAll() { return enable(DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS - | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS); + | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS + | DETECT_VM_FILE_URI_EXPOSURE); } /** @@ -666,6 +672,16 @@ public final class StrictMode { } /** + * Detect when a {@code file://} {@link Uri} is exposed beyond this + * app. The receiving app may not have access to the sent path. + * Instead, when sharing files between apps, {@code content://} + * should be used with permission grants. + */ + public Builder detectFileUriExposure() { + return enable(DETECT_VM_FILE_URI_EXPOSURE); + } + + /** * Crashes the whole process on violation. This penalty runs at * the end of all enabled penalties so yo you'll still get * your logging or other violations before the process dies. @@ -1524,6 +1540,13 @@ public final class StrictMode { /** * @hide */ + public static boolean vmFileUriExposureEnabled() { + return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0; + } + + /** + * @hide + */ public static void onSqliteObjectLeaked(String message, Throwable originStack) { onVmPolicyViolation(message, originStack); } @@ -1549,6 +1572,14 @@ public final class StrictMode { onVmPolicyViolation(null, originStack); } + /** + * @hide + */ + public static void onFileUriExposed(String location) { + final String message = "file:// Uri exposed through " + location; + onVmPolicyViolation(message, new Throwable(message)); + } + // Map from VM violation fingerprint to uptime millis. private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>(); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 79fc51e..83e2e79 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -34,6 +34,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.os.StrictMode; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; @@ -2263,8 +2264,13 @@ public class RemoteViews implements Parcelable, Filter { * @param value The value to pass to the method. */ public void setUri(int viewId, String methodName, Uri value) { - // Resolve any filesystem path before sending remotely - value = value.getCanonicalUri(); + if (value != null) { + // Resolve any filesystem path before sending remotely + value = value.getCanonicalUri(); + if (StrictMode.vmFileUriExposureEnabled()) { + value.checkFileUriExposed("RemoteViews.setUri()"); + } + } addAction(new ReflectionAction(viewId, methodName, ReflectionAction.URI, value)); } |