From 70447223918adc4e858666169e7d88bcfbf3bf6c Mon Sep 17 00:00:00 2001 From: Gavin Corkery Date: Mon, 28 Feb 2022 17:38:13 +0000 Subject: Add isSameApp to PackageManagerInternal Adds a new method to PackageManagerInternal that checks if a given package belongs to the calling uid. This logic also accounts for calling uids in the sdk sandbox range. Deduplicates two methods in NotificationManager and ActivityTaskManager which have implemented this logic. Bug: 219750831 Test: atest NotificationManagerServiceTest Test: Manual test using Sdk Sandbox test app Change-Id: I1c566f75c81112dfeeb664827dcb27768959c377 --- .../android/content/pm/PackageManagerInternal.java | 13 ++++++++++++ .../notification/NotificationManagerService.java | 23 ++-------------------- .../android/server/pm/PackageManagerService.java | 13 ++++++++++++ .../server/wm/ActivityTaskManagerService.java | 14 ++----------- .../NotificationManagerServiceTest.java | 5 +++++ .../NotificationPermissionMigrationTest.java | 5 +++++ 6 files changed, 40 insertions(+), 33 deletions(-) diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index 111bd340a3d1..bd6aa068f488 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -194,6 +194,19 @@ public abstract class PackageManagerInternal { */ public abstract boolean isPermissionsReviewRequired(String packageName, int userId); + + /** + * Gets whether a given package name belongs to the calling uid. If the calling uid is an + * {@link Process#isSdkSandboxUid(int) sdk sandbox uid}, checks whether the package name is + * equal to {@link PackageManager#getSdkSandboxPackageName()}. + * + * @param packageName The package name to check. + * @param callingUid The calling uid. + * @param userId The user under which to check. + * @return True if the package name belongs to the calling uid. + */ + public abstract boolean isSameApp(String packageName, int callingUid, int userId); + /** * Retrieve all of the information we know about a particular package/application. * @param filterCallingUid The results will be filtered in the context of this UID instead diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 050cfeae80b9..c4731aa7b522 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -9650,27 +9650,8 @@ public class NotificationManagerService extends SystemService { if (uid == Process.ROOT_UID && ROOT_PKG.equals(pkg)) { return; } - try { - ApplicationInfo ai = mPackageManager.getApplicationInfo( - pkg, 0, userId); - if (ai == null) { - throw new SecurityException("Unknown package " + pkg); - } - if (!UserHandle.isSameApp(ai.uid, uid)) { - throw new SecurityException("Calling uid " + uid + " gave package " - + pkg + " which is owned by uid " + ai.uid); - } - } catch (RemoteException re) { - throw new SecurityException("Unknown package " + pkg + "\n" + re); - } - } - - private boolean isCallerSameApp(String pkg) { - try { - checkCallerIsSameApp(pkg); - return true; - } catch (SecurityException e) { - return false; + if (!mPackageManagerInternal.isSameApp(pkg, uid, userId)) { + throw new SecurityException("Package " + pkg + " is not owned by uid " + uid); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0602f3e72031..bcfce7be9f7d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -6942,6 +6942,19 @@ public class PackageManagerService extends IPackageManager.Stub return PackageManagerService.this.getKnownPackageNamesInternal(knownPackage, userId); } + @Override + public boolean isSameApp(@Nullable String packageName, int callingUid, int userId) { + if (packageName == null) { + return false; + } + + if (Process.isSdkSandboxUid(callingUid)) { + return packageName.equals(getSdkSandboxPackageName()); + } + int uid = getPackageUid(packageName, 0, userId); + return UserHandle.isSameApp(uid, callingUid); + } + @Override public boolean isResolveActivityComponent(ComponentInfo component) { return mResolveActivity.packageName.equals(component.packageName) diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 062e73d72d1d..bfccdf97c680 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -2232,18 +2232,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { * Return true if callingUid is system, or packageName belongs to that callingUid. */ private boolean isSameApp(int callingUid, @Nullable String packageName) { - try { - if (callingUid != 0 && callingUid != SYSTEM_UID) { - if (packageName == null) { - return false; - } - final int uid = AppGlobals.getPackageManager().getPackageUid(packageName, - PackageManager.MATCH_DEBUG_TRIAGED_MISSING, - UserHandle.getUserId(callingUid)); - return UserHandle.isSameApp(callingUid, uid); - } - } catch (RemoteException e) { - // Should not happen + if (callingUid != 0 && callingUid != SYSTEM_UID) { + return mPmInternal.isSameApp(packageName, callingUid, UserHandle.getUserId(callingUid)); } return true; } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 018a91618564..71f8b8de032b 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -420,6 +420,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { return getApplicationInfo((String) args[0], mUid); }); when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid); + when(mPackageManagerInternal.isSameApp(anyString(), anyInt(), anyInt())).thenAnswer( + (Answer) invocation -> { + Object[] args = invocation.getArguments(); + return (int) args[1] == mUid; + }); final LightsManager mockLightsManager = mock(LightsManager.class); when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class)); when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java index 5a6ca6dc2d14..a83887202a7d 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java @@ -316,6 +316,11 @@ public class NotificationPermissionMigrationTest extends UiServiceTestCase { return getApplicationInfo((String) args[0], mUid); }); when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid); + when(mPackageManagerInternal.isSameApp(anyString(), anyInt(), anyInt())).thenAnswer( + (Answer) invocation -> { + Object[] args = invocation.getArguments(); + return (int) args[1] == mUid; + }); final LightsManager mockLightsManager = mock(LightsManager.class); when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class)); when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); -- cgit v1.2.3-59-g8ed1b