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

Commit ed98f4d0 authored by Adrian Roos's avatar Adrian Roos Committed by Android (Google) Code Review
Browse files

Merge "Revert "Block intents with action set as null""

parents 6b5bf270 8602c625
Loading
Loading
Loading
Loading
+3 −70
Original line number Diff line number Diff line
@@ -20,9 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
@@ -31,7 +28,6 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.PatternMatcher;
import android.os.PersistableBundle;
import android.os.Process;
import android.text.TextUtils;
import android.util.AndroidException;
import android.util.ArraySet;
@@ -185,28 +181,6 @@ public class IntentFilter implements Parcelable {
    private static final String[] EMPTY_STRING_ARRAY = new String[0];
    private static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];

    /**
     * An intent with action set as null used to always pass the action test during intent
     * filter matching. This causes a lot of confusion and unexpected intent matches.
     * Null action intents should be blocked when either the intent sender or receiver
     * application targets U or higher.
     *
     * mBlockNullAction indicates whether the intent filter owner (intent receiver) is
     * targeting U+. This value will be properly set by package manager when IntentFilters are
     * passed to an application, so that when an application is trying to perform intent filter
     * matching locally, the correct matching algorithm will be chosen.
     *
     * When an IntentFilter is sent to system server (e.g. for registering runtime receivers),
     * the value set in mBlockNullAction will be ignored and overwritten with the correct
     * value evaluated based on the Binder calling identity. This makes sure that the
     * security enforcement cannot be bypassed by crafting a malicious IntentFilter.
     *
     * @hide
     */
    @ChangeId
    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    public static final long BLOCK_NULL_ACTION_INTENTS = 264497795;

    /**
     * The filter {@link #setPriority} value at which system high-priority
     * receivers are placed; that is, receivers that should execute before
@@ -354,8 +328,6 @@ public class IntentFilter implements Parcelable {
    private ArrayList<String> mMimeGroups = null;
    private boolean mHasStaticPartialTypes = false;
    private boolean mHasDynamicPartialTypes = false;
    private boolean mBlockNullAction = false;
    private boolean mBlockNullActionEvaluated = false;
    private PersistableBundle mExtras = null;

    private static final int STATE_VERIFY_AUTO         = 0x00000001;
@@ -555,8 +527,6 @@ public class IntentFilter implements Parcelable {
        }
        mHasStaticPartialTypes = o.mHasStaticPartialTypes;
        mHasDynamicPartialTypes = o.mHasDynamicPartialTypes;
        mBlockNullAction = o.getBlockNullAction();
        mBlockNullActionEvaluated = true;
        mVerifyState = o.mVerifyState;
        mInstantAppVisibility = o.mInstantAppVisibility;
    }
@@ -2232,30 +2202,6 @@ public class IntentFilter implements Parcelable {
        return mExtras == null ? new PersistableBundle() : mExtras;
    }

    /**
     * @hide
     */
    public final void setBlockNullAction(boolean blockNullAction) {
        mBlockNullAction = blockNullAction;
        mBlockNullActionEvaluated = true;
    }

    /**
     * @hide
     */
    public final boolean getBlockNullAction() {
        if (!mBlockNullActionEvaluated) {
            if (Process.myUid() == Process.ROOT_UID) {
                // Do not evaluate the boolean when running as root, as we do not want
                // the value to be evaluated when classes are being preloaded in Zygote.
                return true;
            }
            mBlockNullAction = CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS);
            mBlockNullActionEvaluated = true;
        }
        return mBlockNullAction;
    }

    /**
     * Return a {@link Predicate} which tests whether this filter matches the
     * given <var>intent</var>.
@@ -2308,9 +2254,7 @@ public class IntentFilter implements Parcelable {
        String type = resolve ? intent.resolveType(resolver) : intent.getType();
        return match(intent.getAction(), type, intent.getScheme(),
                     intent.getData(), intent.getCategories(), logTag,
                     false /* supportWildcards */,
                     CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS),
                     null /* ignoreActions */,
                     false /* supportWildcards */, null /* ignoreActions */,
                     intent.getExtras());
    }

@@ -2362,7 +2306,6 @@ public class IntentFilter implements Parcelable {
            Uri data, Set<String> categories, String logTag, boolean supportWildcards,
            @Nullable Collection<String> ignoreActions) {
        return match(action, type, scheme, data, categories, logTag, supportWildcards,
                CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS),
                ignoreActions, null /* extras */);
    }

@@ -2370,19 +2313,12 @@ public class IntentFilter implements Parcelable {
     * Variant of {@link #match(String, String, String, Uri, Set, String, boolean, Collection)}
     * that supports matching the extra values in the intent.
     *
     * @param blockNullAction This value decides whether to always block null action regardless
     *                        of the value of mBlockNullAction. Usually this is determined
     *                        by the caller's target SDK value. For more details, check the
     *                        documentation for {@link #BLOCK_NULL_ACTION_INTENTS}.
     *
     * @hide
     */
    public final int match(String action, String type, String scheme,
            Uri data, Set<String> categories, String logTag, boolean supportWildcards,
            boolean blockNullAction, @Nullable Collection<String> ignoreActions,
            @Nullable Bundle extras) {
        if ((action == null && (blockNullAction || getBlockNullAction()))
                || !matchAction(action, supportWildcards, ignoreActions)) {
            @Nullable Collection<String> ignoreActions, @Nullable Bundle extras) {
        if (action != null && !matchAction(action, supportWildcards, ignoreActions)) {
            if (false) Log.v(
                logTag, "No matching action " + action + " for " + this);
            return NO_MATCH_ACTION;
@@ -2917,7 +2853,6 @@ public class IntentFilter implements Parcelable {
        dest.writeInt(mPriority);
        dest.writeInt(mHasStaticPartialTypes ? 1 : 0);
        dest.writeInt(mHasDynamicPartialTypes ? 1 : 0);
        dest.writeInt(getBlockNullAction() ? 1 : 0);
        dest.writeInt(getAutoVerify() ? 1 : 0);
        dest.writeInt(mInstantAppVisibility);
        dest.writeInt(mOrder);
@@ -3027,8 +2962,6 @@ public class IntentFilter implements Parcelable {
        mPriority = source.readInt();
        mHasStaticPartialTypes = source.readInt() > 0;
        mHasDynamicPartialTypes = source.readInt() > 0;
        mBlockNullAction = source.readInt() > 0;
        mBlockNullActionEvaluated = true;
        setAutoVerify(source.readInt() > 0);
        setVisibilityToInstantApp(source.readInt());
        mOrder = source.readInt();
+2 −29
Original line number Diff line number Diff line
@@ -16,17 +16,12 @@

package com.android.server;

import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.compat.CompatChanges;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Binder;
import android.os.Process;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.FastImmutableArraySet;
@@ -39,7 +34,6 @@ import android.util.Slog;
import android.util.proto.ProtoOutputStream;

import com.android.internal.util.FastPrintWriter;
import com.android.server.am.ActivityManagerUtils;
import com.android.server.pm.Computer;
import com.android.server.pm.snapshot.PackageDataSnapshot;

@@ -175,7 +169,7 @@ public abstract class IntentResolver<F, R extends Object> {
        }

        final int match = filter.match(intent.getAction(), resolvedType, intent.getScheme(),
                intent.getData(), intent.getCategories(), TAG, false, false, null, null);
                intent.getData(), intent.getCategories(), TAG);

        if (match >= 0) {
            if (debug) {
@@ -846,28 +840,7 @@ public abstract class IntentResolver<F, R extends Object> {
                continue;
            }

            // IntentFilter#mBlockNullAction indicates whether the intent filter owner
            // (intent receiver) is targeting U+. The blockNullAction local variable here
            // indicates whether the calling process (intent sender) is targeting U+.
            // IntentFilter#mBlockNullAction is ignored here, and will be updated and handled in
            // PackageManagerServiceUtils#applySaferIntentEnforcements.

            // Bypass CompatChanges check when calling UID is SYSTEM_UID as it may be in the
            // system server bootstrapping process and can cause circular dependency.
            final boolean blockNullAction = Binder.getCallingUid() == Process.SYSTEM_UID
                    || CompatChanges.isChangeEnabled(
                            IntentFilter.BLOCK_NULL_ACTION_INTENTS, Binder.getCallingUid());
            // Set this to false as it will be updated and handled later
            intentFilter.setBlockNullAction(false);
            match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG,
                    false /*supportWildcards*/, blockNullAction,
                    null /*ignoreActions*/,
                    null /*extras*/);
            if (action == null) {
                ActivityManagerUtils.logUnsafeIntentEvent(
                        UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH,
                        Binder.getCallingUid(), intent, resolvedType, match < 0);
            }
            match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG);
            if (match >= 0) {
                if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
                        Integer.toHexString(match) + " hasDefault="
+13 −14
Original line number Diff line number Diff line
@@ -101,7 +101,6 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALLOWLISTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
@@ -12715,9 +12714,18 @@ public class ActivityManagerService extends IActivityManager.Stub
            boolean hasToBeExportedToMatch = platformCompat.isChangeEnabledByUid(
                    ActivityManagerService.IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS,
                    callingUid);
            ActivityManagerUtils.logUnsafeIntentEvent(
                    UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH,
                    callingUid, intent, resolvedType, hasToBeExportedToMatch);
            String[] categories = intent.getCategories() == null ? new String[0]
                    : intent.getCategories().toArray(String[]::new);
            FrameworkStatsLog.write(FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED,
                    FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH,
                    callingUid,
                    componentInfo,
                    callerPackage,
                    intent.getAction(),
                    categories,
                    resolvedType,
                    intent.getScheme(),
                    hasToBeExportedToMatch);
            if (!hasToBeExportedToMatch) {
                return;
            }
@@ -13491,10 +13499,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        final boolean visibleToInstantApps
                = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
        // Override the block null action intent information with actual calling UID
        filter.setBlockNullAction(CompatChanges.isChangeEnabled(
                IntentFilter.BLOCK_NULL_ACTION_INTENTS, Binder.getCallingUid()));
        int callingUid;
        int callingPid;
        boolean instantApp;
@@ -13635,12 +13639,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                // provider that needs to lock mProviderMap in ActivityThread
                // and also it may need to wait application response, so we
                // cannot lock ActivityManagerService here.
                if (filter.match(intent.getAction(), intent.resolveType(resolver),
                        intent.getScheme(), intent.getData(), intent.getCategories(), TAG,
                        false /* supportWildcards */,
                        false /* blockNullAction: already evaluated in the beginning */,
                        null /* ignoreActions */,
                        intent.getExtras()) >= 0) {
                if (filter.match(resolver, intent, true, TAG) >= 0) {
                    if (allSticky == null) {
                        allSticky = new ArrayList<Intent>();
                    }
+0 −23
Original line number Diff line number Diff line
@@ -17,13 +17,11 @@ package com.android.server.am;

import android.app.ActivityThread;
import android.content.ContentResolver;
import android.content.Intent;
import android.provider.Settings;
import android.util.ArrayMap;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -135,25 +133,4 @@ public class ActivityManagerUtils {
    public static int hashComponentNameForAtom(String shortInstanceName) {
        return getUnsignedHashUnCached(shortInstanceName) ^ getAndroidIdHash();
    }

    /**
     * Helper method to log an unsafe intent event.
     */
    public static void logUnsafeIntentEvent(int event, int callingUid,
            Intent intent, String resolvedType, boolean blocked) {
        String[] categories = intent.getCategories() == null ? new String[0]
                : intent.getCategories().toArray(String[]::new);
        String component = intent.getComponent() == null ? null
                : intent.getComponent().flattenToString();
        FrameworkStatsLog.write(FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED,
                event,
                callingUid,
                component,
                intent.getPackage(),
                intent.getAction(),
                categories,
                resolvedType,
                intent.getScheme(),
                blocked);
    }
}
+9 −22
Original line number Diff line number Diff line
@@ -16,16 +16,13 @@

package com.android.server.pm;

import static android.content.IntentFilter.BLOCK_NULL_ACTION_INTENTS;
import static android.os.Process.THREAD_PRIORITY_DEFAULT;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.compat.CompatChanges;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
@@ -142,26 +139,19 @@ final class AppsFilterUtils {

    private static boolean matchesPackage(Intent intent, AndroidPackage potentialTarget,
            WatchedArraySet<String> protectedBroadcasts) {
        final boolean blockNullAction = CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS,
                potentialTarget.getPackageName(), UserHandle.SYSTEM);

        if (matchesAnyComponents(
                intent, potentialTarget.getServices(), null /*protectedBroadcasts*/,
                blockNullAction)) {
                intent, potentialTarget.getServices(), null /*protectedBroadcasts*/)) {
            return true;
        }
        if (matchesAnyComponents(
                intent, potentialTarget.getActivities(), null /*protectedBroadcasts*/,
                blockNullAction)) {
                intent, potentialTarget.getActivities(), null /*protectedBroadcasts*/)) {
            return true;
        }
        if (matchesAnyComponents(intent, potentialTarget.getReceivers(), protectedBroadcasts,
                blockNullAction)) {
        if (matchesAnyComponents(intent, potentialTarget.getReceivers(), protectedBroadcasts)) {
            return true;
        }
        if (matchesAnyComponents(
                intent, potentialTarget.getProviders(), null /*protectedBroadcasts*/,
                blockNullAction)) {
                intent, potentialTarget.getProviders(), null /*protectedBroadcasts*/)) {
            return true;
        }
        return false;
@@ -169,14 +159,13 @@ final class AppsFilterUtils {

    private static boolean matchesAnyComponents(Intent intent,
            List<? extends ParsedMainComponent> components,
            WatchedArraySet<String> protectedBroadcasts,
            boolean blockNullAction) {
            WatchedArraySet<String> protectedBroadcasts) {
        for (int i = ArrayUtils.size(components) - 1; i >= 0; i--) {
            ParsedMainComponent component = components.get(i);
            if (!component.isExported()) {
                continue;
            }
            if (matchesAnyFilter(intent, component, protectedBroadcasts, blockNullAction)) {
            if (matchesAnyFilter(intent, component, protectedBroadcasts)) {
                return true;
            }
        }
@@ -184,11 +173,10 @@ final class AppsFilterUtils {
    }

    private static boolean matchesAnyFilter(Intent intent, ParsedComponent component,
            WatchedArraySet<String> protectedBroadcasts, boolean blockNullAction) {
            WatchedArraySet<String> protectedBroadcasts) {
        List<ParsedIntentInfo> intents = component.getIntents();
        for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) {
            IntentFilter intentFilter = intents.get(i).getIntentFilter();
            intentFilter.setBlockNullAction(blockNullAction);
            if (matchesIntentFilter(intent, intentFilter, protectedBroadcasts)) {
                return true;
            }
@@ -199,9 +187,8 @@ final class AppsFilterUtils {
    private static boolean matchesIntentFilter(Intent intent, IntentFilter intentFilter,
            @Nullable WatchedArraySet<String> protectedBroadcasts) {
        return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
                intent.getData(), intent.getCategories(), "AppsFilter", true, false,
                protectedBroadcasts != null ? protectedBroadcasts.untrackedStorage() : null,
                null) > 0;
                intent.getData(), intent.getCategories(), "AppsFilter", true,
                protectedBroadcasts != null ? protectedBroadcasts.untrackedStorage() : null) > 0;
    }

    /**
Loading