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

Commit b542fa01 authored by Nan Wu's avatar Nan Wu
Browse files

Handling intent whose nested intent keys not collected case

We have tried to cover all the public surface of APIs to always
collect nested intent keys. But there could still be cases where
prvileged app calls hide API's that send an intent over IPC but
does not call collectExtraIntentKeys() before. This will cause
those nested intents failed to be launched because they will be
marked as missing creator token. In this CL, we will either throw
an exception when this happens, or collect the keys on the server
side, depends on which flag is enabled.

Bug: 379366027
Test: Manual test.
Flag: android.security.prevent_intent_redirect_throw_exception_if_nested_keys_not_collected
      android.security.prevent_intent_redirect_collect_nested_keys_on_server_if_not_collected

Change-Id: Idb3136b22a892252def272b2f48e085d38aec5fe
parent 56b5042c
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -7720,6 +7720,7 @@ public class Intent implements Parcelable, Cloneable {
    @IntDef(flag = true, prefix = { "EXTENDED_FLAG_" }, value = {
            EXTENDED_FLAG_FILTER_MISMATCH,
            EXTENDED_FLAG_MISSING_CREATOR_OR_INVALID_TOKEN,
            EXTENDED_FLAG_NESTED_INTENT_KEYS_COLLECTED,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ExtendedFlags {}
@@ -7740,6 +7741,13 @@ public class Intent implements Parcelable, Cloneable {
     */
    public static final int EXTENDED_FLAG_MISSING_CREATOR_OR_INVALID_TOKEN = 1 << 1;
    /**
     * This flag indicates this intent called {@link #collectExtraIntentKeys()}.
     *
     * @hide
     */
    public static final int EXTENDED_FLAG_NESTED_INTENT_KEYS_COLLECTED = 1 << 2;
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // toUri() and parseUri() options.
@@ -12328,7 +12336,8 @@ public class Intent implements Parcelable, Cloneable {
    }
    private void collectNestedIntentKeysRecur(Set<Intent> visited) {
        if (mExtras != null && !mExtras.isParcelled() && !mExtras.isEmpty()) {
        addExtendedFlags(EXTENDED_FLAG_NESTED_INTENT_KEYS_COLLECTED);
        if (mExtras != null && !mExtras.isEmpty()) {
            for (String key : mExtras.keySet()) {
                Object value = mExtras.get(key);
+15 −0
Original line number Diff line number Diff line
@@ -95,6 +95,21 @@ flag {
    is_fixed_read_only: true
}

flag {
    name: "prevent_intent_redirect_throw_exception_if_nested_keys_not_collected"
    namespace: "responsible_apis"
    description: "Prevent intent redirect attacks by throwing exception if the intent does not collect nested keys"
    bug: "361143368"
}

flag {
    name: "prevent_intent_redirect_collect_nested_keys_on_server_if_not_collected"
    namespace: "responsible_apis"
    description: "Prevent intent redirect attacks by collecting nested keys on server if not yet collected"
    bug: "361143368"
    is_fixed_read_only: true
}

flag {
    name: "enable_intent_matching_flags"
    is_exported: true
+30 −1
Original line number Diff line number Diff line
@@ -131,6 +131,9 @@ import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
import static android.security.Flags.preventIntentRedirect;
import static android.security.Flags.preventIntentRedirectCollectNestedKeysOnServerIfNotCollected;
import static android.security.Flags.preventIntentRedirectShowToast;
import static android.security.Flags.preventIntentRedirectThrowExceptionIfNestedKeysNotCollected;
import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS;
import static android.view.Display.INVALID_DISPLAY;
@@ -387,6 +390,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.autofill.AutofillManagerInternal;
import android.widget.Toast;
import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
@@ -437,6 +441,7 @@ import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
import com.android.server.ThreadPriorityBooster;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.am.LowMemDetector.MemFactor;
import com.android.server.appop.AppOpsService;
@@ -478,6 +483,7 @@ import com.android.server.wm.WindowProcessController;
import dalvik.annotation.optimization.NeverCompile;
import dalvik.system.VMRuntime;
import libcore.util.EmptyArray;
import java.io.File;
@@ -19304,9 +19310,32 @@ public class ActivityManagerService extends IActivityManager.Stub
     */
    public void addCreatorToken(@Nullable Intent intent, String creatorPackage) {
        if (!preventIntentRedirect()) return;
        if (intent == null) return;
        if ((intent.getExtendedFlags() & Intent.EXTENDED_FLAG_NESTED_INTENT_KEYS_COLLECTED) == 0) {
            Slog.wtf(TAG,
                    "[IntentRedirect] The intent does not have its nested keys collected as a "
                            + "preparation for creating intent creator tokens. Intent: "
                            + intent + "; creatorPackage: " + creatorPackage);
            if (preventIntentRedirectShowToast()) {
                UiThread.getHandler().post(
                        () -> Toast.makeText(mContext,
                                "Nested keys not collected. go/report-bug-intentRedir to report a"
                                        + " bug", Toast.LENGTH_LONG).show());
            }
            if (preventIntentRedirectThrowExceptionIfNestedKeysNotCollected()) {
                // this flag will be internal only, not ramped to public.
                throw new SecurityException(
                        "The intent does not have its nested keys collected as a preparation for "
                                + "creating intent creator tokens. Intent: "
                                + intent + "; creatorPackage: " + creatorPackage);
            }
            if (preventIntentRedirectCollectNestedKeysOnServerIfNotCollected()) {
                // this flag will be ramped to public.
                intent.collectExtraIntentKeys();
            }
        }
        String targetPackage = intent.getComponent() != null
                ? intent.getComponent().getPackageName()
                : intent.getPackage();