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

Commit 9fa6c347 authored by Hani Kazmi's avatar Hani Kazmi Committed by Android (Google) Code Review
Browse files

Merge changes If5e633d1,Ia90b197a

* changes:
  Allow asm finishTask restriction to be enabled.
  Clear out top activities not matching launched uid in task
parents d5e00ade a1bf95bc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ class ActivitySecurityModelFeatureFlags {
    }

    @GuardedBy("ActivityTaskManagerService.mGlobalLock")
    static boolean shouldBlockActivityStart(int uid) {
    static boolean shouldRestrictActivitySwitch(int uid) {
        return flagEnabledForUid(sAsmRestrictionsEnabled, uid);
    }

+51 −1
Original line number Diff line number Diff line
@@ -1972,7 +1972,7 @@ class ActivityStarter {
        );

        boolean shouldBlockActivityStart =
                ActivitySecurityModelFeatureFlags.shouldBlockActivityStart(mCallingUid);
                ActivitySecurityModelFeatureFlags.shouldRestrictActivitySwitch(mCallingUid);

        if (ActivitySecurityModelFeatureFlags.shouldShowToast(mCallingUid)) {
            UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
@@ -2080,6 +2080,7 @@ class ActivityStarter {
                reusedTask != null ? reusedTask.getTopNonFinishingActivity() : null, intentGrants);

        if (mAddingToTask) {
            clearTopIfNeeded(targetTask, mCallingUid, mStartActivity.getUid(), mLaunchFlags);
            return START_SUCCESS;
        }

@@ -2111,6 +2112,55 @@ class ActivityStarter {
        return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
    }

    /**
     * If the top activity uid does not match the launched activity, and the launch was not
     * requested from the top uid, we want to clear out all non matching activities to prevent the
     * top activity being sandwiched.
     */
    private void clearTopIfNeeded(@NonNull Task targetTask, int callingUid, int startingUid,
            int launchFlags) {
        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != FLAG_ACTIVITY_NEW_TASK) {
            // Launch is from the same task, so must be a top or privileged UID
            return;
        }

        ActivityRecord targetTaskTop = targetTask.getTopNonFinishingActivity();
        if (targetTaskTop != null && targetTaskTop.getUid() != startingUid) {
            boolean shouldBlockActivityStart = ActivitySecurityModelFeatureFlags
                    .shouldRestrictActivitySwitch(callingUid);
            int[] finishCount = new int[0];
            if (shouldBlockActivityStart) {
                ActivityRecord activity = targetTask.getActivity(
                        ar -> !ar.finishing && ar.isUid(startingUid));

                if (activity == null) {
                    // mStartActivity is not in task, so clear everything
                    activity = mStartActivity;
                }

                finishCount = new int[1];
                if (activity != null) {
                    targetTask.performClearTop(activity, launchFlags, finishCount);
                }

                if (finishCount[0] > 0) {
                    Slog.w(TAG, "Clearing top n: " + finishCount[0] + " activities from task t: "
                            + targetTask + " not matching top uid: " + callingUid);
                }
            }

            if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)
                    && (!shouldBlockActivityStart || finishCount[0] > 0)) {
                UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
                        (shouldBlockActivityStart
                                ? "Top activities cleared by "
                                : "Top activities would be cleared by ")
                                + ActivitySecurityModelFeatureFlags.DOC_LINK,
                        Toast.LENGTH_SHORT).show());
            }
        }
    }

    /**
     * Check if the activity being launched is the same as the one currently at the top and it
     * should only be launched once.
+26 −2
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.Display;
import android.widget.Toast;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -147,6 +148,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.UiThread;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.HostingRecord;
import com.android.server.am.UserState;
@@ -1628,16 +1630,16 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            // Prevent recursion.
            return;
        }
        boolean passesAsmChecks = true;
        // We may have already checked that the callingUid has additional clearTask privileges, and
        // cleared the calling identify. If so, we infer we do not need further restrictions here.
        // TODO(b/263368846) Move to live with the rest of the ASM logic.
        if (callingUid != SYSTEM_UID) {
            boolean passesAsmChecks = doesTopActivityMatchingUidExistForAsm(task, callingUid,
            passesAsmChecks = doesTopActivityMatchingUidExistForAsm(task, callingUid,
                    null);
            if (!passesAsmChecks) {
                ActivityRecord topActivity =  task.getActivity(ar ->
                        !ar.isState(FINISHING) && !ar.isAlwaysOnTop());
                Slog.i(TAG, "Finishing task from background. t: " + task);
                FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
                        /* caller_uid */
                        callingUid,
@@ -1676,6 +1678,28 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            if (task.isPersistable) {
                mService.notifyTaskPersisterLocked(null, true);
            }
            if (!passesAsmChecks) {
                boolean shouldRestrictActivitySwitch =
                        ActivitySecurityModelFeatureFlags.shouldRestrictActivitySwitch(callingUid);

                if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
                    UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
                            (shouldRestrictActivitySwitch
                                    ? "Returning home due to "
                                    : "Would return home due to ")
                                    + ActivitySecurityModelFeatureFlags.DOC_LINK,
                            Toast.LENGTH_SHORT).show());
                }

                // If the activity switch should be restricted, return home rather than the
                // previously top task, to prevent users from being confused which app they're
                // viewing
                if (shouldRestrictActivitySwitch) {
                    Slog.w(TAG, "Return to home as source uid: " + callingUid
                            + "is not on top of task t: " + task);
                    task.getTaskDisplayArea().moveHomeActivityToTop("taskRemoved");
                }
            }
        } finally {
            task.mInRemoveTask = false;
        }