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

Commit 67a799c9 authored by Hani Kazmi's avatar Hani Kazmi
Browse files

ASM - Bug fixes for clearTopIfNeeded

This includes the following changes:

1. activity starts with UID 0 could fail - they do not have a
   corresponding packageName, resulting in a NPE in the feature flag
   allowlist. We now both explicitely allow UID 0, and check for nulls.

2. We no longer exclude finishing activities in the check. While this is
   generally a no-op, it resulted in noisy logs/toasts. E.G, an activity
   finishes itself and launches a new one with NEW_TASK at the same time
   would result in clearTop being called, even though there is nothing
   to clear.

   This is net-neutral for security - the finishing activity could have
   already morphed itself rather than finishing.

3. We move the home task to front of the finishing tas in
   checkActivitySecurityForTaskClear, rather than to front of display
   area. For multi-window scenarios, this could result in one app
   forcing a home switch for the other.

4. Allow launches from top of stack, even if finishing or alwaysOnTop.
   This supports tasks which are always set to alwaysOnTop, if they try
   to start or finish activities

Bug: 271417931
Test: ABTD with all WM tests and InputMethod tests
Change-Id: I966319723b17f1affd92e141791596e5da644050
parent 341c1972
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ class ActivitySecurityModelFeatureFlags {
    static final String DOC_LINK = "go/android-asm";

    /** Used to determine which version of the ASM logic was used in logs while we iterate */
    static final int ASM_VERSION = 6;
    static final int ASM_VERSION = 7;

    private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER;
    private static final String KEY_ASM_PREFIX = "ActivitySecurity__";
@@ -89,6 +89,9 @@ class ActivitySecurityModelFeatureFlags {

        if (flagEnabled) {
            String[] packageNames = sPm.getPackagesForUid(uid);
            if (packageNames == null) {
                return true;
            }
            for (int i = 0; i < packageNames.length; i++) {
                if (sExcludedPackageNames.contains(packageNames[i])) {
                    return false;
+5 −4
Original line number Diff line number Diff line
@@ -2249,13 +2249,14 @@ class ActivityStarter {
     */
    private void clearTopIfNeeded(@NonNull Task targetTask, int callingUid, int realCallingUid,
            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
        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != FLAG_ACTIVITY_NEW_TASK
                || mBalCode == BAL_ALLOW_ALLOWLISTED_UID) {
            // Launch is from the same task, (a top or privileged UID), or is directly privileged.
            return;
        }

        Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing
                && (ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));
        Predicate<ActivityRecord> isLaunchingOrLaunched = ar ->
                ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid);

        // Return early if we know for sure we won't need to clear any activities by just checking
        // the top activity.
+8 −2
Original line number Diff line number Diff line
@@ -1666,7 +1666,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            String callerActivityClassName) {
        // 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.
        if (callingUid == SYSTEM_UID) {
        if (callingUid == SYSTEM_UID || !task.isVisible() || task.inMultiWindowMode()) {
            return;
        }

@@ -1772,13 +1772,19 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            return new Pair<>(true, true);
        }

        // Always allow actual top activity to clear task
        ActivityRecord topActivity = task.getTopMostActivity();
        if (topActivity != null && topActivity.isUid(uid)) {
            return new Pair<>(true, true);
        }

        // Consider the source activity, whether or not it is finishing. Do not consider any other
        // finishing activity.
        Predicate<ActivityRecord> topOfStackPredicate = (ar) -> ar.equals(sourceRecord)
                || (!ar.finishing && !ar.isAlwaysOnTop());

        // Check top of stack (or the first task fragment for embedding).
        ActivityRecord topActivity = task.getActivity(topOfStackPredicate);
        topActivity = task.getActivity(topOfStackPredicate);
        if (topActivity == null) {
            return new Pair<>(false, false);
        }