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

Commit f41ff188 authored by John Wu's avatar John Wu
Browse files

Enforce intents to match intent filters.

When an app registers an exported component in its manifest and adds an <intent-filter>, the component can be started by any intent - even those that do not match the intent filter. This has proven to be something that many developers find counterintuitive. Without checking the intent when the component is started, in some circumstances this can allow 3P apps to trigger internal-only functionality.

Bug: 161252188
Test: atest CtsContentTestCases:PackageManagerTest
Change-Id: I19e8ee0a529314b3417435471c6e68988a2ab897
parent 6baa40c9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2083,7 +2083,8 @@ public class Instrumentation {
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                            + "; have you declared this activity in your AndroidManifest.xml"
                            + ", or does your intent not match its declared <intent-filter>?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
+6 −0
Original line number Diff line number Diff line
@@ -352,6 +352,12 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
            int filterCallingUid, int userId);


    /**
     * Retrieve all receivers that can handle a broadcast of the given intent.
     */
    public abstract List<ResolveInfo> queryIntentReceivers(Intent intent,
            String resolvedType, int flags, int filterCallingUid, int userId);

    /**
     * Retrieve all services that can be performed for the given intent.
     * @see PackageManager#queryIntentServices(Intent, int)
+41 −0
Original line number Diff line number Diff line
@@ -147,6 +147,47 @@ public abstract class IntentResolver<F, R extends Object> {
        return true;
    }

    /**
     * Returns whether an intent matches the IntentFilter with a pre-resolved type.
     */
    public static boolean intentMatchesFilter(
            IntentFilter filter, Intent intent, String resolvedType) {
        final boolean debug = localLOGV
                || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);

        final Printer logPrinter = debug
                ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM) : null;

        if (debug) {
            Slog.v(TAG, "Intent: " + intent);
            Slog.v(TAG, "Matching against filter: " + filter);
            filter.dump(logPrinter, "  ");
        }

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

        if (match >= 0) {
            if (debug) {
                Slog.v(TAG, "Filter matched!  match=0x" + Integer.toHexString(match));
            }
            return true;
        } else {
            if (debug) {
                final String reason;
                switch (match) {
                    case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
                    case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
                    case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
                    case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
                    default: reason = "unknown reason"; break;
                }
                Slog.v(TAG, "Filter did not match: " + reason);
            }
            return false;
        }
    }

    private ArrayList<F> collectFilters(F[] array, IntentFilter matching) {
        ArrayList<F> res = null;
        if (array != null) {
+54 −59
Original line number Diff line number Diff line
@@ -12628,7 +12628,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
        List<ResolveInfo> receivers = null;
        try {
        HashSet<ComponentName> singleUserReceivers = null;
        boolean scannedFirstReceivers = false;
        for (int user : users) {
@@ -12638,8 +12637,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                    UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
                continue;
            }
                List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                        .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
            List<ResolveInfo> newReceivers = mPackageManagerInt
                    .queryIntentReceivers(intent, resolvedType, pmFlags, callingUid, user);
            if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
                // If this is not the system user, we need to check for
                // any receivers that should be filtered out.
@@ -12696,9 +12695,6 @@ public class ActivityManagerService extends IActivityManager.Stub
                }
            }
        }
        } catch (RemoteException ex) {
            // pm is in same process, this will never happen.
        }
        if (receivers != null && broadcastAllowList != null) {
            for (int i = receivers.size() - 1; i >= 0; i--) {
                final int receiverAppId = UserHandle.getAppId(
@@ -13331,8 +13327,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        List receivers = null;
        List<BroadcastFilter> registeredReceivers = null;
        // Need to resolve the intent to interested receivers...
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
        if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
            receivers = collectReceiverComponents(
                    intent, resolvedType, callingUid, users, broadcastAllowList);
        }
+186 −70

File changed.

Preview size limit exceeded, changes collapsed.