diff options
| author | 2022-02-01 15:15:48 -0800 | |
|---|---|---|
| committer | 2022-02-04 16:58:30 -0800 | |
| commit | 392c84af2c14a1a33944b12bea04766c135cabc9 (patch) | |
| tree | 45e2b50e0f78d7f8fa9265a3a8c7ee95bee8ec48 | |
| parent | da6dafc0bb35958f2ccbb9a451ba4d98864dc328 (diff) | |
Add pkg visibility checks to all hibernation APIs
Ensure that hibernation APIs only return packages that are visible to
the caller UI.
Bug: 216536865
Test: atest AppHibernationTest
Change-Id: I87dba5cb24bf090960680417823c335fcfd084c0
2 files changed, 45 insertions, 7 deletions
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java index 366718c65d84..18e21226503d 100644 --- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java +++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java @@ -230,8 +230,10 @@ public final class AppHibernationService extends SystemService { } final Map<String, UserLevelState> packageStates = mUserStates.get(userId); final UserLevelState pkgState = packageStates.get(packageName); - if (pkgState == null) { - Slog.e(TAG, String.format("Package %s is not installed for user %s", + if (pkgState == null + || !mPackageManagerInternal.canQueryPackage( + Binder.getCallingUid(), packageName)) { + Slog.e(TAG, TextUtils.formatSimple("Package %s is not installed for user %s", packageName, userId)); return false; } @@ -254,7 +256,9 @@ public final class AppHibernationService extends SystemService { "Caller does not have MANAGE_APP_HIBERNATION permission."); synchronized (mLock) { GlobalLevelState state = mGlobalHibernationStates.get(packageName); - if (state == null) { + if (state == null + || !mPackageManagerInternal.canQueryPackage( + Binder.getCallingUid(), packageName)) { // This API can be legitimately called before installation finishes as part of // dex optimization, so we just return false here. return false; @@ -285,8 +289,10 @@ public final class AppHibernationService extends SystemService { } final Map<String, UserLevelState> packageStates = mUserStates.get(realUserId); final UserLevelState pkgState = packageStates.get(packageName); - if (pkgState == null) { - Slog.e(TAG, String.format("Package %s is not installed for user %s", + if (pkgState == null + || !mPackageManagerInternal.canQueryPackage( + Binder.getCallingUid(), packageName)) { + Slog.e(TAG, TextUtils.formatSimple("Package %s is not installed for user %s", packageName, realUserId)); return; } @@ -334,8 +340,11 @@ public final class AppHibernationService extends SystemService { "Caller does not have MANAGE_APP_HIBERNATION permission."); synchronized (mLock) { GlobalLevelState state = mGlobalHibernationStates.get(packageName); - if (state == null) { - Slog.e(TAG, String.format("Package %s is not installed for any user", packageName)); + if (state == null + || !mPackageManagerInternal.canQueryPackage( + Binder.getCallingUid(), packageName)) { + Slog.e(TAG, TextUtils.formatSimple( + "Package %s is not installed for any user", packageName)); return; } if (state.hibernated != isHibernating) { @@ -372,6 +381,12 @@ public final class AppHibernationService extends SystemService { } Map<String, UserLevelState> userStates = mUserStates.get(userId); for (UserLevelState state : userStates.values()) { + String packageName = state.packageName; + if (!mPackageManagerInternal.canQueryPackage( + Binder.getCallingUid(), packageName)) { + // Package is not visible to caller + continue; + } if (state.hibernated) { hibernatingPackages.add(state.packageName); } diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java index e1aa08d9176a..bec094006c8d 100644 --- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java @@ -235,6 +235,29 @@ public final class AppHibernationServiceTest { } @Test + public void testGetHibernatingPackagesForUser_doesNotReturnPackagesThatArentVisible() + throws RemoteException { + // GIVEN an unlocked user with all packages installed but only some are visible to the + // caller + UserInfo userInfo = + addUser(USER_ID_2, new String[]{PACKAGE_NAME_1, PACKAGE_NAME_2, PACKAGE_NAME_3}); + doReturn(false).when(mPackageManagerInternal).canQueryPackage(anyInt(), eq(PACKAGE_NAME_2)); + doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); + mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); + + // WHEN packages are hibernated for the user + mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); + mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_2, true); + + // THEN the hibernating packages returned does not contain the package that was not visible + List<String> hibernatingPackages = + mAppHibernationService.getHibernatingPackagesForUser(USER_ID_2); + assertEquals(1, hibernatingPackages.size()); + assertTrue(hibernatingPackages.contains(PACKAGE_NAME_1)); + assertFalse(hibernatingPackages.contains(PACKAGE_NAME_2)); + } + + @Test public void testUserLevelStatesInitializedFromDisk() throws RemoteException { // GIVEN states stored on disk that match with package manager's force-stop states List<UserLevelState> diskStates = new ArrayList<>(); |