From 0a2b97d635d0ad6d61e99409b9817f8d4662ca71 Mon Sep 17 00:00:00 2001 From: Bernardo Rufino Date: Mon, 11 Jan 2021 14:42:40 +0000 Subject: [PATCH] Restrict StatusBarManager.collapsePanels() for targetSdk < S In order to lock down the abuse vector (b/137274359) we need to restrict this API for targetSdk < S too. So, using the same exemptions of Intent.ACSD to allow legit use-cases, otherwise drop the call instead of throwing because we're not gating it. Also allowing for holders of permission STATUS_BAR since that's the permission we require when targetSdk >= S. Bug: 159105552 Test: CTS coming Test: Verify call to collapsePanels() is not allowed Test: Verify call to collapsePanels() while processing a trampoline with permission EXPAND_STATUS_BAR is allowed Change-Id: I0b986f53df9b7773a33bdd2e57cdd241ff9026b0 --- .../statusbar/StatusBarManagerService.java | 19 +++++++++++++++++-- .../wm/ActivityTaskManagerInternal.java | 5 +++++ .../server/wm/ActivityTaskManagerService.java | 11 +++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index bd2d382c8010d..c08500926650b 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -19,6 +19,7 @@ package com.android.server.statusbar; import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS; import static android.view.Display.DEFAULT_DISPLAY; +import android.Manifest; import android.annotation.Nullable; import android.app.ActivityThread; import android.app.ITransientNotificationCallback; @@ -29,6 +30,7 @@ import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.ComponentName; import android.content.Context; +import android.content.pm.PackageManager; import android.hardware.biometrics.IBiometricSysuiReceiver; import android.hardware.biometrics.PromptInfo; import android.hardware.display.DisplayManager; @@ -74,6 +76,7 @@ import com.android.server.notification.NotificationDelegate; import com.android.server.policy.GlobalActionsProvider; import com.android.server.power.ShutdownCheckPoints; import com.android.server.power.ShutdownThread; +import com.android.server.wm.ActivityTaskManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -113,6 +116,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D private final Object mLock = new Object(); private final DeathRecipient mDeathRecipient = new DeathRecipient(); + private final ActivityTaskManagerInternal mActivityTaskManager; private int mCurrentUserId; private boolean mTracingEnabled; @@ -213,6 +217,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D final DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); displayManager.registerDisplayListener(this, mHandler); + mActivityTaskManager = LocalServices.getService(ActivityTaskManagerInternal.class); } @Override @@ -620,10 +625,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @Override public void collapsePanels() { - if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, Binder.getCallingUid())) { + int uid = Binder.getCallingUid(); + int pid = Binder.getCallingPid(); + if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, uid)) { enforceStatusBar(); } else { - enforceExpandStatusBar(); + if (mContext.checkPermission(Manifest.permission.STATUS_BAR, pid, uid) + != PackageManager.PERMISSION_GRANTED) { + enforceExpandStatusBar(); + if (!mActivityTaskManager.canCloseSystemDialogs(pid, uid)) { + Slog.e(TAG, "Permission Denial: Method collapsePanels() requires permission " + + Manifest.permission.STATUS_BAR + ", ignoring call."); + return; + } + } } if (mBar != null) { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index 08e16c4719a3d..7be362f2a466a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -292,6 +292,11 @@ public abstract class ActivityTaskManagerInternal { public abstract boolean checkCanCloseSystemDialogs(int pid, int uid, @Nullable String packageName); + /** + * Returns whether the app can close system dialogs or not. + */ + public abstract boolean canCloseSystemDialogs(int pid, int uid); + /** * Called after the voice interaction service has changed. */ diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 9b9af0661501b..10f48b7e72b37 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -2958,6 +2958,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { == PERMISSION_GRANTED) { return true; } + if (process == null) { + synchronized (mGlobalLock) { + process = mProcessMap.getProcess(pid); + } + } if (process != null) { // Check if the instrumentation of the process has the permission. This covers the // usual test started from the shell (which has the permission) case. This is needed @@ -5236,6 +5241,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { packageName); } + @Override + public boolean canCloseSystemDialogs(int pid, int uid) { + return ActivityTaskManagerService.this.canCloseSystemDialogs(pid, uid, + null /* process */); + } + @Override public void notifyActiveVoiceInteractionServiceChanged(ComponentName component) { synchronized (mGlobalLock) {