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

Commit b1b1721a authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Merge "Whitelist for package broadcasts" into rvc-dev am: 3dfc45e5"...

Merge "Merge "Whitelist for package broadcasts" into rvc-dev am: 3dfc45e5" into rvc-d1-dev am: 880d82c1 am: e995c573

Change-Id: Ie411972db3a40a79537b0bbf3aaaf73917f04aa5
parents 5d156c96 e995c573
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -403,4 +403,20 @@ public abstract class ActivityManagerInternal {
     * Called by DevicePolicyManagerService to set the uid of the device owner.
     */
    public abstract void setDeviceOwnerUid(int uid);

    /**
     * Sends a broadcast, assuming the caller to be the system and allowing the inclusion of an
     * approved whitelist of app Ids >= {@link android.os.Process#FIRST_APPLICATION_UID} that the
     * broadcast my be sent to; any app Ids < {@link android.os.Process#FIRST_APPLICATION_UID} are
     * automatically whitelisted.
     *
     * @see com.android.server.am.ActivityManagerService#broadcastIntentWithFeature(
     *      IApplicationThread, String, Intent, String, IIntentReceiver, int, String, Bundle,
     *      String[], int, Bundle, boolean, boolean, int)
     */
    public abstract int broadcastIntent(Intent intent,
            IIntentReceiver resultTo,
            String[] requiredPermissions, boolean serialized,
            int userId, int[] appIdWhitelist);

}
+61 −5
Original line number Diff line number Diff line
@@ -15568,7 +15568,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    }
    private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
            int callingUid, int[] users) {
            int callingUid, int[] users, int[] broadcastWhitelist) {
        // TODO: come back and remove this assumption to triage all broadcasts
        int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
@@ -15644,6 +15644,15 @@ public class ActivityManagerService extends IActivityManager.Stub
        } catch (RemoteException ex) {
            // pm is in same process, this will never happen.
        }
        if (receivers != null && broadcastWhitelist != null) {
            for (int i = receivers.size() - 1; i >= 0; i--) {
                final int uid = receivers.get(i).activityInfo.applicationInfo.uid;
                if (uid >= Process.FIRST_APPLICATION_UID
                        && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) {
                    receivers.remove(i);
                }
            }
        }
        return receivers;
    }
@@ -15738,7 +15747,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
                resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
                appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid,
                realCallingPid, userId, false /* allowBackgroundActivityStarts */);
                realCallingPid, userId, false /* allowBackgroundActivityStarts */,
                null /*broadcastWhitelist*/);
    }
    @GuardedBy("this")
@@ -15747,7 +15757,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
            int realCallingPid, int userId, boolean allowBackgroundActivityStarts) {
            int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
            @Nullable int[] broadcastWhitelist) {
        intent = new Intent(intent);
        final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
@@ -15756,6 +15767,12 @@ public class ActivityManagerService extends IActivityManager.Stub
            intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
        }
        if (userId == UserHandle.USER_ALL && broadcastWhitelist != null) {
                Slog.e(TAG, "broadcastWhitelist only applies when sending to individual users. "
                        + "Assuming restrictive whitelist.");
                broadcastWhitelist = new int[]{};
        }
        // By default broadcasts do not go to stopped apps.
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
@@ -16242,7 +16259,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        // Need to resolve the intent to interested receivers...
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
            receivers = collectReceiverComponents(
                    intent, resolvedType, callingUid, users, broadcastWhitelist);
        }
        if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
@@ -16272,6 +16290,17 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
                + " replacePending=" + replacePending);
        if (registeredReceivers != null && broadcastWhitelist != null) {
            // if a uid whitelist was provided, remove anything in the application space that wasn't
            // in it.
            for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
                final int uid = registeredReceivers.get(i).owningUid;
                if (uid >= Process.FIRST_APPLICATION_UID
                        && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) {
                    registeredReceivers.remove(i);
                }
            }
        }
        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        if (!ordered && NR > 0) {
@@ -16555,7 +16584,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType,
                        resultTo, resultCode, resultData, resultExtras, requiredPermissions,
                        OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid,
                        realCallingPid, userId, allowBackgroundActivityStarts);
                        realCallingPid, userId, allowBackgroundActivityStarts,
                        null /*broadcastWhitelist*/);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
@@ -19185,6 +19215,32 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        @Override
        public int broadcastIntent(Intent intent,
                IIntentReceiver resultTo,
                String[] requiredPermissions,
                boolean serialized, int userId, int[] appIdWhitelist) {
            synchronized (ActivityManagerService.this) {
                intent = verifyBroadcastLocked(intent);
                final int callingPid = Binder.getCallingPid();
                final int callingUid = Binder.getCallingUid();
                final long origId = Binder.clearCallingIdentity();
                try {
                    return ActivityManagerService.this.broadcastIntentLocked(null /*callerApp*/,
                            null /*callerPackage*/, null /*callingFeatureId*/, intent,
                            null /*resolvedType*/, resultTo, 0 /*resultCode*/, null /*resultData*/,
                            null /*resultExtras*/, requiredPermissions, AppOpsManager.OP_NONE,
                            null /*options*/, serialized, false /*sticky*/, callingPid, callingUid,
                            callingUid, callingPid, userId, false /*allowBackgroundStarts*/,
                            appIdWhitelist);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
            }
        }
        @Override
        public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
                boolean fgRequired, String callingPackage, @Nullable String callingFeatureId,
+60 −1
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.parsing.pkg.AndroidPackage;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -510,6 +511,64 @@ public class AppsFilter {
                && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
    }

    private static void sort(int[] uids, int nextUidIndex) {
        Arrays.sort(uids, 0, nextUidIndex);
    }

    /**
     * Fetches all app Ids that a given setting is currently visible to, per provided user. This
     * only includes UIDs >= {@link Process#FIRST_APPLICATION_UID} as all other UIDs can already see
     * all applications.
     *
     * If the setting is visible to all UIDs, null is returned. If an app is not visible to any
     * applications, the int array will be empty.
     *
     * @param users the set of users that should be evaluated for this calculation
     * @param existingSettings the set of all package settings that currently exist on device
     * @return a SparseArray mapping userIds to a sorted int array of appIds that may view the
     *         provided setting or null if the app is visible to all and no whitelist should be
     *         applied.
     */
    @Nullable
    public SparseArray<int[]> getVisibilityWhitelist(PackageSetting setting, int[] users,
            ArrayMap<String, PackageSetting> existingSettings) {
        if (mForceQueryable.contains(setting.appId)) {
            return null;
        }
        // let's reserve max memory to limit the number of allocations
        SparseArray<int[]> result = new SparseArray<>(users.length);
        for (int u = 0; u < users.length; u++) {
            final int userId = users[u];
            int[] appIds = new int[existingSettings.size()];
            int[] buffer = null;
            int whitelistSize = 0;
            for (int i = existingSettings.size() - 1; i >= 0; i--) {
                final PackageSetting existingSetting = existingSettings.valueAt(i);
                final int existingAppId = existingSetting.appId;
                if (existingAppId < Process.FIRST_APPLICATION_UID) {
                    continue;
                }
                final int loc = Arrays.binarySearch(appIds, 0, whitelistSize, existingAppId);
                if (loc >= 0) {
                    continue;
                }
                final int existingUid = UserHandle.getUid(userId, existingAppId);
                if (!shouldFilterApplication(existingUid, existingSetting, setting, userId)) {
                    if (buffer == null) {
                        buffer = new int[appIds.length];
                    }
                    final int insert = ~loc;
                    System.arraycopy(appIds, insert, buffer, 0, whitelistSize - insert);
                    appIds[insert] = existingUid;
                    System.arraycopy(buffer, 0, appIds, insert + 1, whitelistSize - insert);
                    whitelistSize++;
                }
            }
            result.put(userId, Arrays.copyOf(appIds, whitelistSize));
        }
        return result;
    }

    /**
     * Removes a package for consideration when filtering visibility between apps.
     *
+93 −64

File changed.

Preview size limit exceeded, changes collapsed.

+55 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.pm;


import static org.hamcrest.Matchers.arrayContaining;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -47,6 +48,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;

import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,7 +58,9 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

@@ -635,6 +639,57 @@ public class AppsFilterTest {
                appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0));
    }

    @Test
    public void testWhoCanSee() throws Exception {
        final AppsFilter appsFilter =
                new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
        appsFilter.onSystemReady();

        final int systemAppId = Process.FIRST_APPLICATION_UID - 1;
        final int seesNothingAppId = Process.FIRST_APPLICATION_UID;
        final int hasProviderAppId = Process.FIRST_APPLICATION_UID + 1;
        final int queriesProviderAppId = Process.FIRST_APPLICATION_UID + 2;
        PackageSetting system = simulateAddPackage(appsFilter, pkg("some.system.pkg"), systemAppId);
        PackageSetting seesNothing = simulateAddPackage(appsFilter, pkg("some.system.pkg"),
                seesNothingAppId);
        PackageSetting hasProvider = simulateAddPackage(appsFilter,
                pkgWithProvider("com.some.package", "com.some.authority"), hasProviderAppId);
        PackageSetting queriesProvider = simulateAddPackage(appsFilter,
                pkgQueriesProvider("com.some.other.package", "com.some.authority"),
                queriesProviderAppId);

        final int[] systemFilter =
                appsFilter.getVisibilityWhitelist(system, new int[]{0}, mExisting).get(0);
        assertThat(Arrays.asList(systemFilter), arrayContaining(systemAppId));

        final int[] seesNothingFilter =
                appsFilter.getVisibilityWhitelist(seesNothing, new int[]{0}, mExisting).get(0);
        assertThat(Arrays.asList(seesNothingFilter),
                arrayContaining(systemAppId, seesNothingAppId));

        final int[] hasProviderFilter =
                appsFilter.getVisibilityWhitelist(hasProvider, new int[]{0}, mExisting).get(0);
        assertThat(Arrays.asList(hasProviderFilter),
                arrayContaining(systemAppId, hasProviderAppId, queriesProviderAppId));

        int[] queriesProviderFilter =
                appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
        assertThat(Arrays.asList(queriesProviderFilter),
                arrayContaining(systemAppId, queriesProviderAppId));

        // provider read
        appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);

        // ensure implicit access is included in the filter
        queriesProviderFilter =
                appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
        assertThat(Arrays.asList(queriesProviderFilter),
                arrayContaining(systemAppId, hasProviderAppId, queriesProviderAppId));
    }

    private void assertThat(List<int[]> asList, Matcher<Integer[]> arrayContainingInAnyOrder) {
    }

    private interface WithSettingBuilder {
        PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
    }
Loading