diff options
| author | Michael Groover <mpgroover@google.com> | 2021-02-26 18:27:16 -0800 |
|---|---|---|
| committer | Michael Groover <mpgroover@google.com> | 2021-02-26 18:27:16 -0800 |
| commit | 96a995dce0fc22b03aa882c76df0d5b03f026c09 (patch) | |
| tree | 9e71510e2ee10c74defc9fac733798489cca8924 /core/java/android/content/Intent.java | |
| parent | 85bde7b023342127bdd85a8eadcb7df0d83221c4 (diff) | |
Report UnsafeIntentLaunchViolation for unfiltered extras copy
Android 12 introduced a new StrictMode check to report an unsafe Intent
launch; initially this was intended to warn developers when a launched
Intent could potentially have originated from an external source. This
commit updates this check to also report when an Intent is being
launched with potentially unfiltered data; that is data that was
copied without sanitation / validation from a parceled Intent or
Bundle. When a violation is reported for unfiltered data the developer
should replace the #putExtras call with individual calls to #putExtra
to only include the items expected in the extras.
Bug: 181374760
Test: atest StrictModeTest
Change-Id: Id2b6baf439716367f4709d03832ceb601f9f009e
Diffstat (limited to 'core/java/android/content/Intent.java')
| -rw-r--r-- | core/java/android/content/Intent.java | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index d53d20a8b192..d352b273f882 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -6755,6 +6755,12 @@ public class Intent implements Parcelable, Cloneable { */ private static final int LOCAL_FLAG_FROM_PROTECTED_COMPONENT = 1 << 2; + /** + * Local flag indicating this instance had unfiltered extras copied into it. This could be + * from either {@link #putExtras(Intent)} when an unparceled Intent is provided or {@link + * #putExtras(Bundle)} when the provided Bundle has not been unparceled. + */ + private static final int LOCAL_FLAG_UNFILTERED_EXTRAS = 1 << 3; // --------------------------------------------------------------------- // --------------------------------------------------------------------- // toUri() and parseUri() options. @@ -10009,6 +10015,15 @@ public class Intent implements Parcelable, Cloneable { mExtras.putAll(src.mExtras); } } + // If the provided Intent was unparceled and this is not an Intent delivered to a protected + // component then mark the extras as unfiltered. An Intent delivered to a protected + // component had to come from a trusted component, and if unfiltered data was copied to the + // delivered Intent then it would have been reported when that Intent left the sending + // process. + if ((src.mLocalFlags & LOCAL_FLAG_FROM_PARCEL) != 0 + && (src.mLocalFlags & LOCAL_FLAG_FROM_PROTECTED_COMPONENT) == 0) { + mLocalFlags |= LOCAL_FLAG_UNFILTERED_EXTRAS; + } return this; } @@ -10023,6 +10038,10 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra */ public @NonNull Intent putExtras(@NonNull Bundle extras) { + // If the provided Bundle has not yet been unparceled then treat this as unfiltered extras. + if (extras.isParcelled()) { + mLocalFlags |= LOCAL_FLAG_UNFILTERED_EXTRAS; + } if (mExtras == null) { mExtras = new Bundle(); } @@ -11328,10 +11347,13 @@ public class Intent implements Parcelable, Cloneable { } // 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); + if (StrictMode.vmUnsafeIntentLaunchEnabled()) { + if ((mLocalFlags & LOCAL_FLAG_FROM_PARCEL) != 0 + && (mLocalFlags & LOCAL_FLAG_FROM_PROTECTED_COMPONENT) == 0) { + StrictMode.onUnsafeIntentLaunch(this); + } else if ((mLocalFlags & LOCAL_FLAG_UNFILTERED_EXTRAS) != 0) { + StrictMode.onUnsafeIntentLaunch(this); + } } } |
