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

Commit 5c111ff6 authored by Gavin Corkery's avatar Gavin Corkery
Browse files

Add checks to allow SDK sandbox uids to broadcast certain intents

Integrates ActivityManager with new in-process APIs defined by
SdkSandboxManagerLocal, which check if a sandbox uid is allowed
to broadcast a given intent or start an activity with a given
intent. If the intent is not allowed, a SecurityException is thrown.

This change also adds several checks to the intent broadcast and
activity starting flow to accommodate the sdk sandbox process. The
goal of these checks is to ensure that something visible to the
user is running inside the SDK sandbox process when a broadcast is
sent or an activity is started.

Bug: 209599396
Test: Manual tests. Send ACTION_VIEW broadcast from sdk sandbox
      testing apps and note that activity starts. Try to send other
      broadcast and note failure.
Change-Id: Ia60e4a062efeef6f281c8bc28343c64f7f3936ab
parent b78bf4e4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -406,6 +406,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.SELinuxUtil;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.pm.snapshot.PackageDataSnapshot;
import com.android.server.sdksandbox.SdkSandboxManagerLocal;
import com.android.server.uri.GrantUri;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -13536,6 +13537,16 @@ public class ActivityManagerService extends IActivityManager.Stub
                intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            }
            if (Process.isSdkSandboxUid(realCallingUid)) {
                SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager(
                        SdkSandboxManagerLocal.class);
                if (sdkSandboxManagerLocal == null) {
                    throw new IllegalStateException("SdkSandboxManagerLocal not found when sending"
                            + " a broadcast from an SDK sandbox uid.");
                }
                sdkSandboxManagerLocal.enforceAllowedToSendBroadcast(intent);
            }
            switch (action) {
                case Intent.ACTION_MEDIA_SCANNER_SCAN_FILE:
                    UserManagerInternal umInternal = LocalServices.getService(
+15 −0
Original line number Diff line number Diff line
@@ -1333,6 +1333,21 @@ class ActivityStarter {
                : (realCallingAppId == Process.SYSTEM_UID)
                        || realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;

        // In the case of an SDK sandbox calling uid, check if the corresponding app uid has a
        // visible window.
        if (Process.isSdkSandboxUid(realCallingUid)) {
            int realCallingSdkSandboxUidToAppUid = Process.getAppUidForSdkSandboxUid(
                    UserHandle.getAppId(realCallingUid));

            if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed: uid in SDK sandbox ("
                            + realCallingUid + ") has visible (non-toast) window.");
                }
                return false;
            }
        }

        // Legacy behavior allows to use caller foreground state to bypass BAL restriction.
        final boolean balAllowedByPiSender =
                PendingIntentRecord.isPendingIntentBalAllowedByCaller(checkedOptions);
+11 −0
Original line number Diff line number Diff line
@@ -244,6 +244,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalManagerRegistry;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
@@ -260,6 +261,7 @@ import com.android.server.am.UserState;
import com.android.server.firewall.IntentFirewall;
import com.android.server.pm.UserManagerService;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.sdksandbox.SdkSandboxManagerLocal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -1236,6 +1238,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
        assertPackageMatchesCallingUid(callingPackage);
        enforceNotIsolatedCaller("startActivityAsUser");
        if (Process.isSdkSandboxUid(Binder.getCallingUid())) {
            SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager(
                    SdkSandboxManagerLocal.class);
            if (sdkSandboxManagerLocal == null) {
                throw new IllegalStateException("SdkSandboxManagerLocal not found when starting"
                        + " an activity from an SDK sandbox uid.");
            }
            sdkSandboxManagerLocal.enforceAllowedToStartActivity(intent);
        }

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ android_test {
        "hamcrest-library",
        "platform-compat-test-rules",
        "CtsSurfaceValidatorLib",
        "service-sdksandbox.impl",
    ],

    libs: [