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

Commit fb92f438 authored by Azhara Assanova's avatar Azhara Assanova
Browse files

Define FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT for PendingIntent

Starting from target SDK U, we want to block creation of mutable
PendingIntents with implicit Intents because attackers can mutate the
Intent object within and launch altered behavior on behalf of victim
apps. For more details on the vulnerability, see go/pendingintent-rca.
This change is planned to be part of the Safer Intents and Components
feature b/229362273.

ag/20580416 is the initial CL that introduced this feature.

This change defines FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT that allows to
bypass the newly introduced block for cases when an implicit intent is
required.

Testing and the actual block will happen in a subsequent CL after we
finish migrating platform code to use safer PendingIntents. For now,
there is a Slog.wtfStack() that acts as a warning about the upcoming
change.

Bug: 236704164
Bug: 229362273
Test: atest PendingIntentTest
CTS-Coverage-Bug: 266434003
Change-Id: I701f7e3ab3e95deb5b8b6990c5d67b7d66a052b0
parent 37ea02ca
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6725,6 +6725,7 @@ package android.app {
    method public static void writePendingIntentOrNullToParcel(@Nullable android.app.PendingIntent, @NonNull android.os.Parcel);
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.app.PendingIntent> CREATOR;
    field public static final int FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT = 16777216; // 0x1000000
    field public static final int FLAG_CANCEL_CURRENT = 268435456; // 0x10000000
    field public static final int FLAG_IMMUTABLE = 67108864; // 0x4000000
    field public static final int FLAG_MUTABLE = 33554432; // 0x2000000
+25 −4
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ public final class PendingIntent implements Parcelable {
                    FLAG_IMMUTABLE,
                    FLAG_MUTABLE,
                    FLAG_MUTABLE_UNAUDITED,
                    FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT,

                    Intent.FILL_IN_ACTION,
                    Intent.FILL_IN_DATA,
@@ -279,6 +280,21 @@ public final class PendingIntent implements Parcelable {
    @TestApi
    public static final int FLAG_MUTABLE_UNAUDITED = FLAG_MUTABLE;

    /**
     * Flag indicating that the created PendingIntent with {@link #FLAG_MUTABLE}
     * is allowed to have an unsafe implicit Intent within. <p>Starting with
     * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, for apps that
     * target SDK {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or
     * higher, creation of a PendingIntent with {@link #FLAG_MUTABLE} and an
     * implicit Intent within will throw an {@link IllegalArgumentException}
     * for security reasons. To bypass this check, use
     * {@link #FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT} when creating a PendingIntent.
     * However, it is strongly recommended to not to use this flag and make the
     * Intent explicit or the PendingIntent immutable, thereby making the Intent
     * safe.
     */
    public static final int FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT = 1<<24;

    /**
     * Exception thrown when trying to send through a PendingIntent that
     * has been canceled or is otherwise no longer able to execute the request.
@@ -418,12 +434,13 @@ public final class PendingIntent implements Parcelable {
        //   This will be changed to a throw of an exception on the server side once we finish
        //   migrating to safer PendingIntents b/262253127.
        // - Otherwise, warn that it will be blocked from target SDK U.
        if (isNewMutableImplicitPendingIntent(flags, intent)) {
        if (isNewMutableDisallowedImplicitPendingIntent(flags, intent)) {
            if (Compatibility.isChangeEnabled(BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT)) {
                String msg = packageName + ": Targeting U+ (version "
                        + Build.VERSION_CODES.UPSIDE_DOWN_CAKE + " and above) disallows"
                        + " creating or retrieving a PendingIntent with FLAG_MUTABLE,"
                        + " an implicit Intent within and without FLAG_NO_CREATE for"
                        + " an implicit Intent within and without FLAG_NO_CREATE and"
                        + " FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT for"
                        + " security reasons. To retrieve an already existing"
                        + " PendingIntent, use FLAG_NO_CREATE, however, to create a"
                        + " new PendingIntent with an implicit Intent use"
@@ -441,11 +458,15 @@ public final class PendingIntent implements Parcelable {
    }

    /** @hide */
    public static boolean isNewMutableImplicitPendingIntent(int flags, @NonNull Intent intent) {
    public static boolean isNewMutableDisallowedImplicitPendingIntent(int flags,
            @NonNull Intent intent) {
        boolean isFlagNoCreateSet = (flags & PendingIntent.FLAG_NO_CREATE) != 0;
        boolean isFlagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0;
        boolean isImplicit = (intent.getComponent() == null) && (intent.getPackage() == null);
        return !isFlagNoCreateSet && isFlagMutableSet && isImplicit;
        boolean isFlagAllowUnsafeImplicitIntentSet =
                (flags & PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT) != 0;
        return !isFlagNoCreateSet && isFlagMutableSet && isImplicit
                && !isFlagAllowUnsafeImplicitIntentSet;
    }

    /**