From d2ceb2ba6105c6137c27f92f03e874053e6d12f6 Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Fri, 10 Sep 2021 12:36:26 +0800 Subject: Limiting activity embedding to the activities of the same app Disallow having cross-app activities being embedded until we have a better understanding and solutions to deal with potential security issues. Also not allow embedding tasks even belongs to the same app because the activities of another app could still be launched on the embedded task afterward. Only system is allowed to embed tasks. Bug: 189386461 Bug: 197364677 Test: atest TaskFragmentOrganizerPolicyTest Change-Id: Ib6ca8783449872f035fffe51743c5a966768c894 --- .../com/android/server/wm/ActivityStarter.java | 51 +++++++++++++--------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 71ac73091986..bab5a616a5c9 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -16,7 +16,6 @@ package com.android.server.wm; -import static android.Manifest.permission.ACTIVITY_EMBEDDING; import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.app.Activity.RESULT_CANCELED; import static android.app.ActivityManager.START_ABORTED; @@ -1953,38 +1952,43 @@ class ActivityStarter { } } - if (mInTaskFragment != null && mInTaskFragment.getTask() != null) { - final int hostUid = mInTaskFragment.getTask().effectiveUid; - final int embeddingUid = targetTask != null ? targetTask.effectiveUid : r.getUid(); - if (!canTaskBeEmbedded(hostUid, embeddingUid)) { - Slog.e(TAG, "Cannot embed activity to a task owned by " + hostUid + " targetTask= " - + targetTask); - return START_PERMISSION_DENIED; - } + if (mInTaskFragment != null && !canEmbedActivity(mInTaskFragment, r, newTask, targetTask)) { + Slog.e(TAG, "Permission denied: Cannot embed " + r + " to " + mInTaskFragment.getTask() + + " targetTask= " + targetTask); + return START_PERMISSION_DENIED; } return START_SUCCESS; } /** - * Return {@code true} if the {@param task} can embed another task. - * @param hostUid the uid of the host task - * @param embeddedUid the uid of the task the are going to be embedded + * Return {@code true} if an activity can be embedded to the TaskFragment. + * @param taskFragment the TaskFragment for embedding. + * @param starting the starting activity. + * @param newTask whether the starting activity is going to be launched on a new task. + * @param targetTask the target task for launching activity, which could be different from + * the one who hosting the embedding. */ - private boolean canTaskBeEmbedded(int hostUid, int embeddedUid) { + private boolean canEmbedActivity(@NonNull TaskFragment taskFragment, ActivityRecord starting, + boolean newTask, Task targetTask) { + final Task hostTask = taskFragment.getTask(); + if (hostTask == null) { + return false; + } + // Allowing the embedding if the task is owned by system. + final int hostUid = hostTask.effectiveUid; if (hostUid == Process.SYSTEM_UID) { return true; } - // Allowing embedding if the host task is owned by an app that has the ACTIVITY_EMBEDDING - // permission - if (mService.checkPermission(ACTIVITY_EMBEDDING, -1, hostUid) == PERMISSION_GRANTED) { - return true; + // Not allowed embedding an activity of another app. + if (hostUid != starting.getUid()) { + return false; } - // Allowing embedding if it is from the same app that owned the task - return hostUid == embeddedUid; + // Not allowed embedding task. + return !newTask && (targetTask == null || targetTask == hostTask); } /** @@ -2801,10 +2805,15 @@ class ActivityStarter { newParent = mInTaskFragment; } } else { - // Use the child TaskFragment (if any) as the new parent if the activity can be embedded final ActivityRecord top = task.topRunningActivity(false /* focusableOnly */, false /* includingEmbeddedTask */); - newParent = top != null ? top.getTaskFragment() : task; + final TaskFragment taskFragment = top != null ? top.getTaskFragment() : null; + if (taskFragment != null && taskFragment.isEmbedded() + && task.effectiveUid == mStartActivity.getUid()) { + // Use the embedded TaskFragment of the top activity as the new parent if the + // activity can be embedded. + newParent = top.getTaskFragment(); + } } if (mStartActivity.getTaskFragment() == null -- cgit v1.2.3-59-g8ed1b