From 85a9add6bdacee1b310ff1a3d01b53f3460a3d1a Mon Sep 17 00:00:00 2001 From: Sudheer Shanka Date: Mon, 25 Apr 2022 15:36:27 -0700 Subject: [PATCH] Verify INTERACT_ACROSS_USERS_FULL perm for cross-user calls. Bug: 218338453 Bug: 217935264 Test: atest tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java Change-Id: I3ef13204834e04228280a73e8a095720d5e854a3 --- core/api/test-current.txt | 4 ++-- core/java/android/app/ActivityManager.java | 17 +++++++++++++++-- core/java/android/app/IActivityManager.aidl | 4 ++++ .../server/am/ActivityManagerService.java | 10 ++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/core/api/test-current.txt b/core/api/test-current.txt index f4a12a5a6a0f3..eee5c917fc4f7 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -116,8 +116,8 @@ package android.app { method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener); method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName); method public long getTotalRam(); - method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidProcessCapabilities(int); - method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidProcessState(int); + method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessCapabilities(int); + method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessState(int); method public void holdLock(android.os.IBinder, int); method public static boolean isHighEndGfx(); method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 458dd5d804d14..abd60177f8844 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -3710,10 +3710,16 @@ public class ActivityManager { /** * Returns the process state of this uid. * + * If the caller does not hold {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL} + * permission, they can only query process state of UIDs running in the same user as the caller. + * * @hide */ @TestApi - @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) + @RequiresPermission(allOf = { + Manifest.permission.PACKAGE_USAGE_STATS, + Manifest.permission.INTERACT_ACROSS_USERS_FULL + }, conditional = true) public int getUidProcessState(int uid) { try { return getService().getUidProcessState(uid, mContext.getOpPackageName()); @@ -3725,10 +3731,17 @@ public class ActivityManager { /** * Returns the process capability of this uid. * + * If the caller does not hold {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL} + * permission, they can only query process capabilities of UIDs running in the same user + * as the caller. + * * @hide */ @TestApi - @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) + @RequiresPermission(allOf = { + Manifest.permission.PACKAGE_USAGE_STATS, + Manifest.permission.INTERACT_ACROSS_USERS_FULL + }, conditional = true) public @ProcessCapability int getUidProcessCapabilities(int uid) { try { return getService().getUidProcessCapabilities(uid, mContext.getOpPackageName()); diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 49a61580ab3b8..4efe9dfe71855 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -100,6 +100,8 @@ interface IActivityManager { String callingPackage); void unregisterUidObserver(in IUidObserver observer); boolean isUidActive(int uid, String callingPackage); + @JavaPassthrough(annotation= + "@android.annotation.RequiresPermission(allOf = {android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional = true)") int getUidProcessState(int uid, in String callingPackage); @UnsupportedAppUsage int checkPermission(in String permission, int pid, int uid); @@ -742,6 +744,8 @@ interface IActivityManager { /** Called by PendingIntent.queryIntentComponents() */ ParceledListSlice queryIntentComponentsForIntentSender(in IIntentSender sender, int matchFlags); + @JavaPassthrough(annotation= + "@android.annotation.RequiresPermission(allOf = {android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional = true)") int getUidProcessCapabilities(int uid, in String callingPackage); /** Blocks until all broadcast queues become idle. */ diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 35f7e064e3587..33ff5d629b09f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7204,6 +7204,11 @@ public class ActivityManagerService extends IActivityManager.Stub enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, "getUidProcessState"); } + // In case the caller is requesting processState of an app in a different user, + // then verify the caller has INTERACT_ACROSS_USERS_FULL permission + mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), + UserHandle.getUserId(uid), false /* allowAll */, ALLOW_FULL_ONLY, + "getUidProcessState", callingPackage); // Ignore return value synchronized (mProcLock) { if (mPendingStartActivityUids.isPendingTopUid(uid)) { @@ -7219,6 +7224,11 @@ public class ActivityManagerService extends IActivityManager.Stub enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, "getUidProcessState"); } + // In case the caller is requesting processCapabilities of an app in a different user, + // then verify the caller has INTERACT_ACROSS_USERS_FULL permission + mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), + UserHandle.getUserId(uid), false /* allowAll */, ALLOW_FULL_ONLY, + "getUidProcessCapabilities", callingPackage); // Ignore return value synchronized (mProcLock) { return mProcessList.getUidProcessCapabilityLOSP(uid);