From 1cba31c3dc307a8629d32434bd5846a0097c240a Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Wed, 28 Jun 2017 09:42:48 -0700 Subject: [PATCH] Restrict launching activities on virtual displays If an app creates a Surface and a virtual display backed by that Surface, it can then launch activities and hijack their content. This CL restrict activities that can be launched to virtual displays created by apps only to those who set "allowEmbedded" attribute. If a virtual display was created by system, apps won't get access to the surface, so we're not limiting in this case. Bug: 63094482 Test: android.server.cts.ActivityManagerDisplayTests Test: #testLaunchNotEmbeddedOnVirtualDisplay Change-Id: Ied216bdf33df4b5a6cc8cac0e006a4883a36f94f --- .../server/am/ActivityStackSupervisor.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index fe0e07efe9bcc..50233f360a33f 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -38,11 +38,13 @@ import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCRE import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.os.Process.SYSTEM_UID; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; +import static android.view.Display.TYPE_VIRTUAL; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; @@ -1654,7 +1656,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // owner. final int launchDisplayId = options.getLaunchDisplayId(); if (launchDisplayId != INVALID_DISPLAY - && !isCallerAllowedToLaunchOnDisplay(callingPid, callingUid, launchDisplayId)) { + && !isCallerAllowedToLaunchOnDisplay(callingPid, callingUid, launchDisplayId, + aInfo)) { final String msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ") with launchDisplayId=" @@ -1668,7 +1671,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } /** Check if caller is allowed to launch activities on specified display. */ - boolean isCallerAllowedToLaunchOnDisplay(int callingPid, int callingUid, int launchDisplayId) { + boolean isCallerAllowedToLaunchOnDisplay(int callingPid, int callingUid, int launchDisplayId, + ActivityInfo aInfo) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check: displayId=" + launchDisplayId + " callingPid=" + callingPid + " callingUid=" + callingUid); @@ -1678,6 +1682,25 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return false; } + // Check if the caller can manage activity stacks. + final int startAnyPerm = mService.checkPermission(MANAGE_ACTIVITY_STACKS, callingPid, + callingUid); + if (startAnyPerm == PERMISSION_GRANTED) { + if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + + " allow launch any on display"); + return true; + } + + if (activityDisplay.mDisplay.getType() == TYPE_VIRTUAL + && activityDisplay.mDisplay.getOwnerUid() != SYSTEM_UID + && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) { + // Limit launching on virtual displays, because their contents can be read from Surface + // by apps that created them. + if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + + " disallow launch on virtual display for not-embedded activity"); + return false; + } + if (!activityDisplay.isPrivate()) { // Anyone can launch on a public display. if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" @@ -1699,15 +1722,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } - // Check if the caller can manage activity stacks. - final int startAnyPerm = mService.checkPermission(MANAGE_ACTIVITY_STACKS, callingPid, - callingUid); - if (startAnyPerm == PERMISSION_GRANTED) { - if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" - + " allow launch any on display"); - return true; - } - Slog.w(TAG, "Launch on display check: denied"); return false; }