summaryrefslogtreecommitdiff
path: root/core/java/android/content/Intent.java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2021-01-15 20:53:21 -0700
committerMichael Groover <mpgroover@google.com>2021-01-20 13:05:09 -0800
commit6728d4f92caa8a344b225cfbc1b257d14cd8c273 (patch)
tree0072a8dfe6e9fca3f8fecb57838d2f695956ac81 /core/java/android/content/Intent.java
parentfd763b652d75b12b65251d6a7d4aede5465a3d3e (diff)
Add StrictMode check for unsafe intent launching
Exported components that are not guarded by a signature permission can receive Intents from any other app on a device. If an app unparcels and launches an Intent from the Intent delivered to this unprotected component then a malicious actor can potentially craft an Intent that could launch hidden components, grant URI permissions, etc. This commit adds a StrictMode check to report if a component launches an Intent unparceled from the delivered Intent. Bug: 160796858 Test: atest StrictModeTest Change-Id: I763b8a965f91f5b433ce2f4b619e10ef12f5c296
Diffstat (limited to 'core/java/android/content/Intent.java')
-rw-r--r--core/java/android/content/Intent.java46
1 files changed, 44 insertions, 2 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7843d97aa411..1752b480c06b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6681,6 +6681,25 @@ public class Intent implements Parcelable, Cloneable {
| FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| FLAG_GRANT_PREFIX_URI_PERMISSION;
+ /**
+ * Local flag indicating this instance was created by copy constructor.
+ */
+ private static final int LOCAL_FLAG_FROM_COPY = 1 << 0;
+
+ /**
+ * Local flag indicating this instance was created from a {@link Parcel}.
+ */
+ private static final int LOCAL_FLAG_FROM_PARCEL = 1 << 1;
+
+ /**
+ * Local flag indicating this instance was delivered through a protected
+ * component, such as an activity that requires a signature permission, or a
+ * protected broadcast. Note that this flag <em>cannot</em> be recursively
+ * applied to any contained instances, since a malicious app may have
+ * controlled them via {@link #fillIn(Intent, int)}.
+ */
+ private static final int LOCAL_FLAG_FROM_PROTECTED_COMPONENT = 1 << 2;
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// toUri() and parseUri() options.
@@ -6798,6 +6817,8 @@ public class Intent implements Parcelable, Cloneable {
private String mPackage;
private ComponentName mComponent;
private int mFlags;
+ /** Set of in-process flags which are never parceled */
+ private int mLocalFlags;
private ArraySet<String> mCategories;
@UnsupportedAppUsage
private Bundle mExtras;
@@ -6848,6 +6869,11 @@ public class Intent implements Parcelable, Cloneable {
this.mCategories = new ArraySet<>(o.mCategories);
}
+ // Inherit flags from the original, plus mark that we were
+ // created by this copy constructor
+ this.mLocalFlags = o.mLocalFlags;
+ this.mLocalFlags |= LOCAL_FLAG_FROM_COPY;
+
if (copyMode != COPY_MODE_FILTER) {
this.mFlags = o.mFlags;
this.mContentUserHint = o.mContentUserHint;
@@ -10931,6 +10957,9 @@ public class Intent implements Parcelable, Cloneable {
/** @hide */
protected Intent(Parcel in) {
+ // Remember that we came from a remote process to help detect security
+ // issues caused by later unsafe launches
+ mLocalFlags = LOCAL_FLAG_FROM_PARCEL;
readFromParcel(in);
}
@@ -11242,18 +11271,27 @@ public class Intent implements Parcelable, Cloneable {
mData = Uri.fromFile(after);
}
}
+
+ // Detect cases where we're about to launch a potentially unsafe intent
+ if ((mLocalFlags & LOCAL_FLAG_FROM_PARCEL) != 0
+ && (mLocalFlags & LOCAL_FLAG_FROM_PROTECTED_COMPONENT) == 0
+ && StrictMode.vmUnsafeIntentLaunchEnabled()) {
+ StrictMode.onUnsafeIntentLaunch(this);
+ }
}
/**
* @hide
*/
- public void prepareToEnterProcess() {
+ public void prepareToEnterProcess(boolean fromProtectedComponent) {
// We just entered destination process, so we should be able to read all
// parcelables inside.
setDefusable(true);
if (mSelector != null) {
- mSelector.prepareToEnterProcess();
+ // We can't recursively claim that this data is from a protected
+ // component, since it may have been filled in by a malicious app
+ mSelector.prepareToEnterProcess(false);
}
if (mClipData != null) {
mClipData.prepareToEnterProcess();
@@ -11265,6 +11303,10 @@ public class Intent implements Parcelable, Cloneable {
mContentUserHint = UserHandle.USER_CURRENT;
}
}
+
+ if (fromProtectedComponent) {
+ mLocalFlags |= LOCAL_FLAG_FROM_PROTECTED_COMPONENT;
+ }
}
/** @hide */