Merge changes If5e633d1,Ia90b197a

* changes:
  Allow asm finishTask restriction to be enabled.
  Clear out top activities not matching launched uid in task
This commit is contained in:
Hani Kazmi
2023-01-24 12:21:58 +00:00
committed by Android (Google) Code Review
3 changed files with 78 additions and 4 deletions

View File

@@ -72,7 +72,7 @@ class ActivitySecurityModelFeatureFlags {
}
@GuardedBy("ActivityTaskManagerService.mGlobalLock")
static boolean shouldBlockActivityStart(int uid) {
static boolean shouldRestrictActivitySwitch(int uid) {
return flagEnabledForUid(sAsmRestrictionsEnabled, uid);
}

View File

@@ -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.

View File

@@ -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;
}