diff options
| author | 2022-12-19 14:30:05 +0000 | |
|---|---|---|
| committer | 2023-01-03 19:12:15 +0000 | |
| commit | a09a8f1c8caffd571f1db14b939d5c7efd9270eb (patch) | |
| tree | c30a6ffaf27df2033661c9251b1f09956527622d | |
| parent | 3ad4f200c29703cf36ebc88f2f9c6f738cf7ee41 (diff) | |
Add restriction to remove main user
Add restriction to remove main user when system property
MAIN_USER_PERMANENT_ADMIN is set to true.
Bug: 260200162
Test: atest UserManagerTest -c
Change-Id: Ibce0d8275eed131fad794503924d52ad31b540c2
5 files changed, 82 insertions, 7 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 712ac94216d3..3bb90f7801aa 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -10380,6 +10380,7 @@ package android.os { field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background"; field public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2; // 0x2 field public static final int REMOVE_RESULT_DEFERRED = 1; // 0x1 + field public static final int REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN = -5; // 0xfffffffb field public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4; // 0xfffffffc field public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1; // 0xffffffff field public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3; // 0xfffffffd diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 99152347106f..73e52a799cef 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1824,6 +1824,15 @@ public class UserManager { public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4; /** + * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that + * user being removed is a {@link UserInfo#FLAG_MAIN} user and can't be removed because + * system property {@link com.android.internal.R.bool.isMainUserPermanentAdmin} is true. + * @hide + */ + @SystemApi + public static final int REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN = -5; + + /** * Possible response codes from {@link #removeUserWhenPossible(UserHandle, boolean)}. * * @hide @@ -1835,6 +1844,7 @@ public class UserManager { REMOVE_RESULT_ERROR_USER_RESTRICTION, REMOVE_RESULT_ERROR_USER_NOT_FOUND, REMOVE_RESULT_ERROR_SYSTEM_USER, + REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN, REMOVE_RESULT_ERROR_UNKNOWN, }) @Retention(RetentionPolicy.SOURCE) @@ -5224,8 +5234,9 @@ public class UserManager { * @return the {@link RemoveResult} code: {@link #REMOVE_RESULT_REMOVED}, * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED}, * {@link #REMOVE_RESULT_ERROR_USER_RESTRICTION}, {@link #REMOVE_RESULT_ERROR_USER_NOT_FOUND}, - * {@link #REMOVE_RESULT_ERROR_SYSTEM_USER}, or {@link #REMOVE_RESULT_ERROR_UNKNOWN}. All error - * codes have negative values. + * {@link #REMOVE_RESULT_ERROR_SYSTEM_USER}, + * {@link #REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN}, or + * {@link #REMOVE_RESULT_ERROR_UNKNOWN}. All error codes have negative values. * * @hide */ diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 2138c205ee58..55bc0f416846 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -3012,6 +3012,10 @@ class PackageManagerShellCommand extends ShellCommand { case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED: getOutPrintWriter().printf("Success: user %d is already being removed\n", userId); return 0; + case UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN: + getOutPrintWriter().printf("Error: user %d is a permanent admin main user\n", + userId); + return 1; default: getErrPrintWriter().printf("Error: couldn't remove or mark ephemeral user id %d\n", userId); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 6bac90532645..b4d35a17fb1f 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -5426,6 +5426,12 @@ public class UserManagerService extends IUserManager.Stub { return false; } + if (isNonRemovableMainUser(userData.info)) { + Slog.e(LOG_TAG, "Main user cannot be removed when " + + "it's a permanent admin user."); + return false; + } + if (mRemovingUserIds.get(userId)) { Slog.e(LOG_TAG, TextUtils.formatSimple( "User %d is already scheduled for removal.", userId)); @@ -5530,6 +5536,12 @@ public class UserManagerService extends IUserManager.Stub { return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND; } + if (isNonRemovableMainUser(userData.info)) { + Slog.e(LOG_TAG, "Main user cannot be removed when " + + "it's a permanent admin user."); + return UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN; + } + if (mRemovingUserIds.get(userId)) { Slog.e(LOG_TAG, "User " + userId + " is already scheduled for removal."); return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED; @@ -6748,7 +6760,7 @@ public class UserManagerService extends IUserManager.Stub { public void removeAllUsers() { if (UserHandle.USER_SYSTEM == getCurrentUserId()) { // Remove the non-system users straight away. - removeNonSystemUsers(); + removeAllUsersExceptSystemAndPermanentAdminMain(); } else { // Switch to the system user first and then remove the other users. BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() { @@ -6760,7 +6772,7 @@ public class UserManagerService extends IUserManager.Stub { return; } mContext.unregisterReceiver(this); - removeNonSystemUsers(); + removeAllUsersExceptSystemAndPermanentAdminMain(); } }; IntentFilter userSwitchedFilter = new IntentFilter(); @@ -7113,14 +7125,14 @@ public class UserManagerService extends IUserManager.Stub { throw new UserManager.CheckedUserOperationException(message, userOperationResult); } - /* Remove all the users except of the system one. */ - private void removeNonSystemUsers() { + /* Remove all the users except the system and permanent admin main.*/ + private void removeAllUsersExceptSystemAndPermanentAdminMain() { ArrayList<UserInfo> usersToRemove = new ArrayList<>(); synchronized (mUsersLock) { final int userSize = mUsers.size(); for (int i = 0; i < userSize; i++) { UserInfo ui = mUsers.valueAt(i).info; - if (ui.id != UserHandle.USER_SYSTEM) { + if (ui.id != UserHandle.USER_SYSTEM && !isNonRemovableMainUser(ui)) { usersToRemove.add(ui); } } @@ -7249,4 +7261,22 @@ public class UserManagerService extends IUserManager.Stub { return mAmInternal; } + /** + * Returns true, when user has {@link UserInfo#FLAG_MAIN} and system property + * {@link com.android.internal.R.bool.isMainUserPermanentAdmin} is true. + */ + private boolean isNonRemovableMainUser(UserInfo userInfo) { + return userInfo.isMain() && isMainUserPermanentAdmin(); + } + + /** + * Returns true, when {@link com.android.internal.R.bool.isMainUserPermanentAdmin} is true. + * If the main user is a permanent admin user it can't be deleted + * or downgraded to non-admin status. + */ + private static boolean isMainUserPermanentAdmin() { + return Resources.getSystem() + .getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin); + } + } diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index 5059ef3d1e3a..4f4980699627 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -373,6 +373,29 @@ public final class UserManagerTest { @MediumTest @Test + public void testRemoveUserWhenPossible_permanentAdminMainUserReturnsError() throws Exception { + assumeHeadlessModeEnabled(); + assumeTrue("Main user is not permanent admin", isMainUserPermanentAdmin()); + + int currentUser = ActivityManager.getCurrentUser(); + final UserInfo otherUser = createUser("User 1", /* flags= */ UserInfo.FLAG_ADMIN); + UserHandle mainUser = mUserManager.getMainUser(); + + switchUser(otherUser.id, null, true); + + assertThat(mUserManager.removeUserWhenPossible(mainUser, + /* overrideDevicePolicy= */ false)) + .isEqualTo(UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN); + + + assertThat(hasUser(mainUser.getIdentifier())).isTrue(); + + // Switch back to the starting user. + switchUser(currentUser, null, true); + } + + @MediumTest + @Test public void testRemoveUserWhenPossible_invalidUserReturnsError() throws Exception { assertThat(hasUser(Integer.MAX_VALUE)).isFalse(); assertThat(mUserManager.removeUserWhenPossible(UserHandle.of(Integer.MAX_VALUE), @@ -1420,4 +1443,10 @@ public final class UserManagerTest { private static UserHandle asHandle(int userId) { return new UserHandle(userId); } + + private boolean isMainUserPermanentAdmin() { + return Resources.getSystem() + .getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin); + } + } |