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
This commit is contained in:
Nikhil Kumar
2022-12-19 14:30:05 +00:00
parent 3ad4f200c2
commit a09a8f1c8c
5 changed files with 82 additions and 7 deletions

View File

@@ -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

View File

@@ -1823,6 +1823,15 @@ public class UserManager {
@SystemApi
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)}.
*
@@ -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
*/

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -371,6 +371,29 @@ public final class UserManagerTest {
assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue();
}
@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 {
@@ -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);
}
}