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

Commit d92605d2 authored by Hani Kazmi's avatar Hani Kazmi
Browse files

Update ASM clearTask Logging

As part of go/activity-security, we introduced logging on finishActivity
in ag/19950589. This will be used to decide if we can block an activity
from finishing it's task if it is not on top of it's stack.

A case was missed - apps can also clearTask through
`appTask.finishAndRemoveTask()`, which follows a different code path.
To include this, and centralise the code, logging has been moved a level
down, and callerUid passed through where needed.

There are other callers as well, i.e from RecentTasks.java, but they
already enforce MANAGE_TASKS permission, so I've tried to minimise
callerUid having to be passed through from there for these other cases.

Bug: 246738504
Test: statsd_testdrive 495
Test: Manually reproduced scenario and checked logs

Change-Id: Ibc5b830217d6219cb8a0e620bf800c1ffa7a52a3
parent 55cac928
Loading
Loading
Loading
Loading
+1 −35
Original line number Diff line number Diff line
@@ -98,7 +98,6 @@ import com.android.internal.app.AssistUtils;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.LocalServices;
import com.android.server.Watchdog;
import com.android.server.pm.KnownPackages;
@@ -467,46 +466,13 @@ class ActivityClientController extends IActivityClientController.Stub {
                        finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
                if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
                        || (finishWithRootActivity && r == rootR)) {
                    ActivityRecord topActivity =
                            r.getTask().getTopNonFinishingActivity();
                    boolean passesAsmChecks = topActivity != null
                            && topActivity.getUid() == r.getUid();
                    if (!passesAsmChecks) {
                        Slog.i(TAG, "Finishing task from background. r: " + r);
                        FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
                                /* caller_uid */
                                r.getUid(),
                                /* caller_activity_class_name */
                                r.info.name,
                                /* target_task_top_activity_uid */
                                topActivity == null ? -1 : topActivity.getUid(),
                                /* target_task_top_activity_class_name */
                                topActivity == null ? null : topActivity.info.name,
                                /* target_task_is_different */
                                false,
                                /* target_activity_uid */
                                -1,
                                /* target_activity_class_name */
                                null,
                                /* target_intent_action */
                                null,
                                /* target_intent_flags */
                                0,
                                /* action */
                                FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__FINISH_TASK,
                                /* version */
                                1,
                                /* multi_window */
                                false
                        );
                    }
                    // If requested, remove the task that is associated to this activity only if it
                    // was the root activity in the task. The result code and data is ignored
                    // because we don't support returning them across task boundaries. Also, to
                    // keep backwards compatibility we remove the task from recents when finishing
                    // task with root activity.
                    mTaskSupervisor.removeTask(tr, false /*killProcess*/,
                            finishWithRootActivity, "finish-activity");
                            finishWithRootActivity, "finish-activity", r.getUid(), r.info.name);
                    res = true;
                    // Explicitly dismissing the activity so reset its relaunch flag.
                    r.mRelaunchReason = RELAUNCH_REASON_NONE;
+46 −3
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.protolog.common.ProtoLog;
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.am.ActivityManagerService;
@@ -1601,11 +1602,11 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
     * @return Returns true if the given task was found and removed.
     */
    boolean removeTaskById(int taskId, boolean killProcess, boolean removeFromRecents,
            String reason) {
            String reason, int callingUid) {
        final Task task =
                mRootWindowContainer.anyTaskForId(taskId, MATCH_ATTACHED_TASK_OR_RECENT_TASKS);
        if (task != null) {
            removeTask(task, killProcess, removeFromRecents, reason);
            removeTask(task, killProcess, removeFromRecents, reason, callingUid, null);
            return true;
        }
        Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId);
@@ -1613,10 +1614,52 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
    }

    void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) {
        removeTask(task, killProcess, removeFromRecents, reason, SYSTEM_UID, null);
    }

    void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason,
            int callingUid, String callerActivityClassName) {
        if (task.mInRemoveTask) {
            // Prevent recursion.
            return;
        }
        // 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) {
            ActivityRecord topActivity = task.getTopNonFinishingActivity();
            boolean passesAsmChecks = topActivity != null
                    && topActivity.getUid() == callingUid;
            if (!passesAsmChecks) {
                Slog.i(TAG, "Finishing task from background. t: " + task);
                FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
                        /* caller_uid */
                        callingUid,
                        /* caller_activity_class_name */
                        callerActivityClassName,
                        /* target_task_top_activity_uid */
                        topActivity == null ? -1 : topActivity.getUid(),
                        /* target_task_top_activity_class_name */
                        topActivity == null ? null : topActivity.info.name,
                        /* target_task_is_different */
                        false,
                        /* target_activity_uid */
                        -1,
                        /* target_activity_class_name */
                        null,
                        /* target_intent_action */
                        null,
                        /* target_intent_flags */
                        0,
                        /* action */
                        FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__FINISH_TASK,
                        /* version */
                        1,
                        /* multi_window */
                        false
                );
            }
        }
        task.mTransitionController.requestCloseTransitionIfNeeded(task);
        task.mInRemoveTask = true;
        try {
@@ -1739,7 +1782,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            // Task was trimmed from the recent tasks list -- remove the active task record as well
            // since the user won't really be able to go back to it
            removeTaskById(task.mTaskId, killProcess, false /* removeFromRecents */,
                    "recent-task-trimmed");
                    "recent-task-trimmed", SYSTEM_UID);
        }
        task.removedFromRecents();
    }
+4 −3
Original line number Diff line number Diff line
@@ -72,15 +72,16 @@ class AppTaskImpl extends IAppTask.Stub {
        checkCallerOrSystemOrRoot();

        synchronized (mService.mGlobalLock) {
            final long origId = Binder.clearCallingIdentity();
            int origCallingUid = Binder.getCallingUid();
            final long callingIdentity = Binder.clearCallingIdentity();
            try {
                // We remove the task from recents to preserve backwards
                if (!mService.mTaskSupervisor.removeTaskById(mTaskId, false,
                        REMOVE_FROM_RECENTS, "finish-and-remove-task")) {
                        REMOVE_FROM_RECENTS, "finish-and-remove-task", origCallingUid)) {
                    throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
                }
            } finally {
                Binder.restoreCallingIdentity(origId);
                Binder.restoreCallingIdentity(callingIdentity);
            }
        }
    }