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

Commit 880d82c1 authored by Automerger Merge Worker's avatar Automerger Merge Worker Committed by Android (Google) Code Review
Browse files

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

parents da256df2 97def78e
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -403,4 +403,20 @@ public abstract class ActivityManagerInternal {
     * Called by DevicePolicyManagerService to set the uid of the device owner.
     * Called by DevicePolicyManagerService to set the uid of the device owner.
     */
     */
    public abstract void setDeviceOwnerUid(int uid);
    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 Original line Diff line number Diff line
@@ -15568,7 +15568,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    }
    }
    private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
    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
        // TODO: come back and remove this assumption to triage all broadcasts
        int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
        int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
@@ -15644,6 +15644,15 @@ public class ActivityManagerService extends IActivityManager.Stub
        } catch (RemoteException ex) {
        } catch (RemoteException ex) {
            // pm is in same process, this will never happen.
            // 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;
        return receivers;
    }
    }
@@ -15738,7 +15747,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
        return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
                resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
                resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
                appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid,
                appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid,
                realCallingPid, userId, false /* allowBackgroundActivityStarts */);
                realCallingPid, userId, false /* allowBackgroundActivityStarts */,
                null /*broadcastWhitelist*/);
    }
    }
    @GuardedBy("this")
    @GuardedBy("this")
@@ -15747,7 +15757,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            IIntentReceiver resultTo, int resultCode, String resultData,
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
            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);
        intent = new Intent(intent);
        final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
        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);
            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.
        // By default broadcasts do not go to stopped apps.
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
        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...
        // Need to resolve the intent to interested receivers...
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
                 == 0) {
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
            receivers = collectReceiverComponents(
                    intent, resolvedType, callingUid, users, broadcastWhitelist);
        }
        }
        if (intent.getComponent() == null) {
        if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
            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()
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
                + " replacePending=" + replacePending);
                + " 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;
        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        if (!ordered && NR > 0) {
        if (!ordered && NR > 0) {
@@ -16555,7 +16584,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType,
                return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType,
                        resultTo, resultCode, resultData, resultExtras, requiredPermissions,
                        resultTo, resultCode, resultData, resultExtras, requiredPermissions,
                        OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid,
                        OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid,
                        realCallingPid, userId, allowBackgroundActivityStarts);
                        realCallingPid, userId, allowBackgroundActivityStarts,
                        null /*broadcastWhitelist*/);
            } finally {
            } finally {
                Binder.restoreCallingIdentity(origId);
                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
        @Override
        public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
        public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
                boolean fgRequired, String callingPackage, @Nullable String callingFeatureId,
                boolean fgRequired, String callingPackage, @Nullable String callingFeatureId,
+60 −1
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@ import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackage;


import java.io.PrintWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.Set;
@@ -510,6 +511,64 @@ public class AppsFilter {
                && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
                && 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.
     * 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 Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.pm;
package com.android.server.pm;




import static org.hamcrest.Matchers.arrayContaining;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
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.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;


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


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


@@ -635,6 +639,57 @@ public class AppsFilterTest {
                appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0));
                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 {
    private interface WithSettingBuilder {
        PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
        PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
    }
    }
Loading