Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96a995dc authored by Michael Groover's avatar Michael Groover
Browse files

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
parent 85bde7b0
Loading
Loading
Loading
Loading
+26 −4
Original line number Diff line number Diff line
@@ -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,12 +11347,15 @@ public class Intent implements Parcelable, Cloneable {
        }

        // Detect cases where we're about to launch a potentially unsafe intent
        if (StrictMode.vmUnsafeIntentLaunchEnabled()) {
            if ((mLocalFlags & LOCAL_FLAG_FROM_PARCEL) != 0
                && (mLocalFlags & LOCAL_FLAG_FROM_PROTECTED_COMPONENT) == 0
                && StrictMode.vmUnsafeIntentLaunchEnabled()) {
                    && (mLocalFlags & LOCAL_FLAG_FROM_PROTECTED_COMPONENT) == 0) {
                StrictMode.onUnsafeIntentLaunch(this);
            } else if ((mLocalFlags & LOCAL_FLAG_UNFILTERED_EXTRAS) != 0) {
                StrictMode.onUnsafeIntentLaunch(this);
            }
        }
    }

    /**
     * @hide