diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index dc0e249d72ec3..69d564fc610be 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1141,6 +1141,8 @@ public class UserManager { UserInfo user = null; try { user = mService.createUser(name, flags); + // TODO: Keep this in sync with + // UserManagerService.LocalService.createUserEvenWhenDisallowed if (user != null && !user.isAdmin()) { mService.setUserRestriction(DISALLOW_SMS, true, user.id); mService.setUserRestriction(DISALLOW_OUTGOING_CALLS, true, user.id); diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java index 58a026904373c..d2ece8bba3ad1 100644 --- a/core/java/android/os/UserManagerInternal.java +++ b/core/java/android/os/UserManagerInternal.java @@ -17,6 +17,7 @@ package android.os; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.UserInfo; import android.graphics.Bitmap; /** @@ -106,4 +107,12 @@ public abstract class UserManagerInternal { * non-ephemeral users left. */ public abstract void removeAllUsers(); + + /** + * Same as UserManager.createUser(), but bypasses the check for DISALLOW_ADD_USER. + * + *

Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when + * createAndManageUser is called by the device owner. + */ + public abstract UserInfo createUserEvenWhenDisallowed(String name, int flags); } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 3cc7b10c6f242..22d09944d13f7 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1789,6 +1789,10 @@ public class UserManagerService extends IUserManager.Stub { Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled."); return null; } + return createUserInternalUnchecked(name, flags, parentId); + } + + private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) { if (ActivityManager.isLowRamDeviceStatic()) { return null; } @@ -2975,6 +2979,17 @@ public class UserManagerService extends IUserManager.Stub { am.switchUser(UserHandle.USER_SYSTEM); } } + + @Override + public UserInfo createUserEvenWhenDisallowed(String name, int flags) { + UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL); + // Keep this in sync with UserManager.createUser + if (user != null && !user.isAdmin()) { + setUserRestriction(UserManager.DISALLOW_SMS, true, user.id); + setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, true, user.id); + } + return user; + } } /* Remove all the users except of the system one. */ diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index b7138d29cc937..6aabfa3e77a2d 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -6791,6 +6791,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { throw new IllegalArgumentException("profileOwner " + profileOwner + " and admin " + admin + " are not in the same package"); } + // Only allow the system user to use this method + if (!mInjector.binderGetCallingUserHandle().isSystem()) { + throw new SecurityException("createAndManageUser was called from non-system user"); + } // Create user. UserHandle user = null; synchronized (this) { @@ -6802,7 +6806,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if ((flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0) { userInfoFlags |= UserInfo.FLAG_EPHEMERAL; } - UserInfo userInfo = mUserManager.createUser(name, userInfoFlags); + UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name, + userInfoFlags); if (userInfo != null) { user = userInfo.getUserHandle(); }