Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e64034a2 authored by Sudheer Shanka's avatar Sudheer Shanka Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE: Reduce shell power over user management." into lmp-dev

parents 41821a26 65f53e14
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1454,6 +1454,14 @@
        android:label="@string/permlab_manageUsers"
        android:description="@string/permdesc_manageUsers" />

    <!-- @hide Allows an application to create, remove users and get the list of
         users on the device. Applications holding this permission can only create restricted,
         guest, and managed users. For creating other kind of users,
         {@link android.Manifest.permission#MANAGE_USERS} is needed.
         This permission is not available to third party applications. -->
    <permission android:name="android.permission.CREATE_USERS"
        android:protectionLevel="signature" />

    <!-- Allows an application to get full detailed information about
         recently running tasks, with full fidelity to the real state.
         @hide -->
+1 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@
    <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
    <uses-permission android:name="android.permission.MANAGE_USERS" />
    <uses-permission android:name="android.permission.CREATE_USERS" />
    <uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
    <uses-permission android:name="android.permission.BLUETOOTH_STACK" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+76 −6
Original line number Diff line number Diff line
@@ -117,6 +117,11 @@ public class UserManagerService extends IUserManager.Stub {
    private static final String RESTRICTIONS_FILE_PREFIX = "res_";
    private static final String XML_SUFFIX = ".xml";

    private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
            UserInfo.FLAG_MANAGED_PROFILE
            | UserInfo.FLAG_RESTRICTED
            | UserInfo.FLAG_GUEST;

    private static final int MIN_USER_ID = 10;

    private static final int USER_VERSION = 5;
@@ -272,7 +277,7 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public List<UserInfo> getUsers(boolean excludeDying) {
        checkManageUsersPermission("query users");
        checkManageOrCreateUsersPermission("query users");
        synchronized (mPackagesLock) {
            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
            for (int i = 0; i < mUsers.size(); i++) {
@@ -291,7 +296,7 @@ public class UserManagerService extends IUserManager.Stub {
    @Override
    public List<UserInfo> getProfiles(int userId, boolean enabledOnly) {
        if (userId != UserHandle.getCallingUserId()) {
            checkManageUsersPermission("getting profiles related to user " + userId);
            checkManageOrCreateUsersPermission("getting profiles related to user " + userId);
        }
        final long ident = Binder.clearCallingIdentity();
        try {
@@ -361,7 +366,7 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public UserInfo getUserInfo(int userId) {
        checkManageUsersPermission("query user");
        checkManageOrCreateUsersPermission("query user");
        synchronized (mPackagesLock) {
            return getUserInfoLocked(userId);
        }
@@ -578,6 +583,71 @@ public class UserManagerService extends IUserManager.Stub {
        }
    }

    /**
     * Enforces that only the system UID or root's UID or apps that have the
     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}
     * can make certain calls to the UserManager.
     *
     * @param message used as message if SecurityException is thrown
     * @throws SecurityException if the caller is not system or root
     * @see #hasManageOrCreateUsersPermission()
     */
    private static final void checkManageOrCreateUsersPermission(String message) {
        if (!hasManageOrCreateUsersPermission()) {
            throw new SecurityException(
                    "You either need MANAGE_USERS or CREATE_USERS permission to: " + message);
        }
    }

    /**
     * Similar to {@link #checkManageOrCreateUsersPermission(String)} but when the caller is tries
     * to create user/profiles other than what is allowed for
     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} permission, then it will only
     * allow callers with {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} permission.
     */
    private static final void checkManageOrCreateUsersPermission(int creationFlags) {
        if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
            if (!hasManageOrCreateUsersPermission()) {
                throw new SecurityException("You either need MANAGE_USERS or CREATE_USERS "
                        + "permission to create an user with flags: " + creationFlags);
            }
        } else if (!hasManageUsersPermission()) {
            throw new SecurityException("You need MANAGE_USERS permission to create an user "
                    + " with flags: " + creationFlags);
        }
    }

    /**
     * @return whether the calling UID is system UID or root's UID or the calling app has the
     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}.
     */
    private static final boolean hasManageUsersPermission() {
        final int callingUid = Binder.getCallingUid();
        return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
                || callingUid == Process.ROOT_UID
                || ActivityManager.checkComponentPermission(
                        android.Manifest.permission.MANAGE_USERS,
                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * @return whether the calling UID is system UID or root's UID or the calling app has the
     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}.
     */
    private static final boolean hasManageOrCreateUsersPermission() {
        final int callingUid = Binder.getCallingUid();
        return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
                || callingUid == Process.ROOT_UID
                || ActivityManager.checkComponentPermission(
                        android.Manifest.permission.MANAGE_USERS,
                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED
                || ActivityManager.checkComponentPermission(
                        android.Manifest.permission.CREATE_USERS,
                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
    }

    private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
        try {
            File dir = new File(mUsersDir, Integer.toString(info.id));
@@ -1135,7 +1205,7 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public UserInfo createProfileForUser(String name, int flags, int userId) {
        checkManageUsersPermission("Only the system can create users");
        checkManageOrCreateUsersPermission(flags);
        if (userId != UserHandle.USER_OWNER) {
            Slog.w(LOG_TAG, "Only user owner can have profiles");
            return null;
@@ -1145,7 +1215,7 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public UserInfo createUser(String name, int flags) {
        checkManageUsersPermission("Only the system can create users");
        checkManageOrCreateUsersPermission(flags);
        return createUserInternal(name, flags, UserHandle.USER_NULL);
    }

@@ -1297,7 +1367,7 @@ public class UserManagerService extends IUserManager.Stub {
     * @param userHandle the user's id
     */
    public boolean removeUser(int userHandle) {
        checkManageUsersPermission("Only the system can remove users");
        checkManageOrCreateUsersPermission("Only the system can remove users");
        if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
                UserManager.DISALLOW_REMOVE_USER, false)) {
            Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
+5 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.AppGlobals;
@@ -3747,7 +3748,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        if (!mHasFeature) {
            return false;
        }
        if (ActivityManager.checkComponentPermission(android.Manifest.permission.CREATE_USERS,
              Binder.getCallingUid(), -1, true) == PackageManager.PERMISSION_DENIED) {
            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
        }

        UserInfo info = mUserManager.getUserInfo(userHandle);
        if (info == null) {