From a5e0a4f770ca1ca0163be4b367e2ae1747ba1758 Mon Sep 17 00:00:00 2001 From: Antonio Kantek Date: Wed, 9 Mar 2022 19:00:00 -0800 Subject: [PATCH] Check instrumentation source UID in setInstrumenting In order to allow switching touch mode, WindowManagerService checks if caller has MODIFY_TOUCH_MODE_STATE permission OR if the process is instrumeting. Just checking if process is instrumenting may not be enough since apps can self instrument themselves. To avoid that, we're now also checking if the instrumentation source is shell (which has the permission pointed out above granted) or root. Bug: 222652344 Test: atest ActivityTaskManagerServiceTests Change-Id: I55078d5c223d4f936d58199d3d013e07a6747a1e --- .../android/server/wm/ActivityTaskManagerService.java | 11 ++++++++--- .../com/android/server/wm/WindowManagerService.java | 9 +++++---- .../android/server/wm/WindowManagerServiceTests.java | 11 +++++++---- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 8b6262f0fccaa..ad6f354520511 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -5303,14 +5303,19 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /** * Returns {@code true} if the process represented by the pid passed as argument is - * instrumented. + * instrumented and the instrumentation source was granted with the permission also + * passed as argument. */ - boolean isInstrumenting(int pid) { + boolean instrumentationSourceHasPermission(int pid, String permission) { final WindowProcessController process; synchronized (mGlobalLock) { process = mProcessMap.getProcess(pid); } - return process != null ? process.isInstrumenting() : false; + if (process == null || !process.isInstrumenting()) { + return false; + } + final int sourceUid = process.getInstrumentationSourceUid(); + return checkPermission(permission, -1, sourceUid) == PackageManager.PERMISSION_GRANTED; } final class H extends Handler { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 43e84ae911184..29e292da5697e 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3760,7 +3760,8 @@ public class WindowManagerService extends IWindowManager.Stub * Sets the touch mode state. * * To be able to change touch mode state, the caller must either own the focused window, or must - * have the MODIFY_TOUCH_MODE_STATE permission. Instrumented processes are allowed to switch + * have the {@link android.Manifest.permission#MODIFY_TOUCH_MODE_STATE} permission. Instrumented + * process, sourced with {@link android.Manifest.permission#MODIFY_TOUCH_MODE_STATE}, may switch * touch mode at any time. * * @param mode the touch mode to set @@ -3773,9 +3774,9 @@ public class WindowManagerService extends IWindowManager.Stub } final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); - - final boolean hasPermission = mAtmService.isInstrumenting(pid) - || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()"); + final boolean hasPermission = + mAtmService.instrumentationSourceHasPermission(pid, MODIFY_TOUCH_MODE_STATE) + || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()"); final long token = Binder.clearCallingIdentity(); try { if (mInputManager.setInTouchMode(mode, pid, uid, hasPermission)) { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java index 08320f8c423fe..9d4fe27839928 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java @@ -70,7 +70,7 @@ import org.junit.runner.RunWith; /** * Build/Install/Run: - * atest WmTests:WindowManagerServiceTests + * atest WmTests:WindowManagerServiceTests */ @SmallTest @Presubmit @@ -266,7 +266,8 @@ public class WindowManagerServiceTests extends WindowTestsBase { final WindowToken windowToken = createTestWindowToken(TYPE_INPUT_METHOD, mDefaultDisplay); final Session session = new Session(mWm, new IWindowSessionCallback.Stub() { @Override - public void onAnimatorScaleChanged(float v) throws RemoteException {} + public void onAnimatorScaleChanged(float v) throws RemoteException { + } }); final WindowManager.LayoutParams params = new WindowManager.LayoutParams( TYPE_APPLICATION_ATTACHED_DIALOG); @@ -292,7 +293,8 @@ public class WindowManagerServiceTests extends WindowTestsBase { int callingPid = Binder.getCallingPid(); int callingUid = Binder.getCallingUid(); doReturn(false).when(mWm).checkCallingPermission(anyString(), anyString()); - when(mWm.mAtmService.isInstrumenting(callingPid)).thenReturn(true); + when(mWm.mAtmService.instrumentationSourceHasPermission(callingPid, + android.Manifest.permission.MODIFY_TOUCH_MODE_STATE)).thenReturn(true); mWm.setInTouchMode(!currentTouchMode); @@ -306,7 +308,8 @@ public class WindowManagerServiceTests extends WindowTestsBase { int callingPid = Binder.getCallingPid(); int callingUid = Binder.getCallingUid(); doReturn(false).when(mWm).checkCallingPermission(anyString(), anyString()); - when(mWm.mAtmService.isInstrumenting(callingPid)).thenReturn(false); + when(mWm.mAtmService.instrumentationSourceHasPermission(callingPid, + android.Manifest.permission.MODIFY_TOUCH_MODE_STATE)).thenReturn(false); mWm.setInTouchMode(!currentTouchMode);