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

Commit 01576869 authored by Esteban Talavera's avatar Esteban Talavera
Browse files

Enforce DISALLOW_ADD_MANAGED_PROFILE

Only the device owner should be able to create a managed
profile if that restriction is set

Test: runtest -c com.android.server.devicepolicy.DevicePolicyManagerTest    frameworks-services

Bug: 31952368

Change-Id: Ia5170e54594ccba1e5bcedffaec98c2af42264c0
parent bcdc5d74
Loading
Loading
Loading
Loading
+42 −26
Original line number Diff line number Diff line
@@ -385,7 +385,7 @@ public class DevicePolicyManager {
            "com.android.server.action.BUGREPORT_SHARING_DECLINED";

    /**
     * Action: Bugreport has been collected and is dispatched to {@link DevicePolicyManagerService}.
     * Action: Bugreport has been collected and is dispatched to {@code DevicePolicyManagerService}.
     *
     * @hide
     */
@@ -1165,7 +1165,7 @@ public class DevicePolicyManager {
    public @interface UserProvisioningState {}

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
     * {@link #ACTION_PROVISION_MANAGED_PROFILE}, {@link #ACTION_PROVISION_MANAGED_USER} and
@@ -1176,7 +1176,7 @@ public class DevicePolicyManager {
    public static final int CODE_OK = 0;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
     * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the device already has a device
@@ -1187,7 +1187,7 @@ public class DevicePolicyManager {
    public static final int CODE_HAS_DEVICE_OWNER = 1;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
     * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the user has a profile owner and for
@@ -1198,7 +1198,7 @@ public class DevicePolicyManager {
    public static final int CODE_USER_HAS_PROFILE_OWNER = 2;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
     * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the user isn't running.
@@ -1208,7 +1208,7 @@ public class DevicePolicyManager {
    public static final int CODE_USER_NOT_RUNNING = 3;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
     * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} if the device has already been setup and
@@ -1233,7 +1233,7 @@ public class DevicePolicyManager {
    public static final int CODE_ACCOUNTS_NOT_EMPTY = 6;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
     * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} if the user is not a system user.
@@ -1243,7 +1243,7 @@ public class DevicePolicyManager {
    public static final int CODE_NOT_SYSTEM_USER = 7;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
     * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} and {@link #ACTION_PROVISION_MANAGED_USER}
@@ -1254,7 +1254,7 @@ public class DevicePolicyManager {
    public static final int CODE_HAS_PAIRED = 8;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} and
     * {@link #ACTION_PROVISION_MANAGED_USER} on devices which do not support managed users.
@@ -1265,7 +1265,7 @@ public class DevicePolicyManager {
    public static final int CODE_MANAGED_USERS_NOT_SUPPORTED = 9;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} if the user is a system user.
     *
@@ -1274,7 +1274,7 @@ public class DevicePolicyManager {
    public static final int CODE_SYSTEM_USER = 10;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when the user cannot have more
     * managed profiles.
@@ -1284,7 +1284,7 @@ public class DevicePolicyManager {
    public static final int CODE_CANNOT_ADD_MANAGED_PROFILE = 11;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} and
     * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} on devices not running with split system
@@ -1295,7 +1295,7 @@ public class DevicePolicyManager {
    public static final int CODE_NOT_SYSTEM_USER_SPLIT = 12;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
     * {@link #ACTION_PROVISION_MANAGED_PROFILE}, {@link #ACTION_PROVISION_MANAGED_USER} and
@@ -1307,7 +1307,7 @@ public class DevicePolicyManager {
    public static final int CODE_DEVICE_ADMIN_NOT_SUPPORTED = 13;

    /**
     * Result code for {@link checkProvisioningPreCondition}.
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when the device the user is a
     * system user on a split system user device.
@@ -1317,7 +1317,17 @@ public class DevicePolicyManager {
    public static final int CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER = 14;

    /**
     * Result codes for {@link checkProvisioningPreCondition} indicating all the provisioning pre
     * Result code for {@link #checkProvisioningPreCondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when adding a managed profile is
     * disallowed by {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
     *
     * @hide
     */
    public static final int CODE_ADD_MANAGED_PROFILE_DISALLOWED = 15;

    /**
     * Result codes for {@link #checkProvisioningPreCondition} indicating all the provisioning pre
     * conditions.
     *
     * @hide
@@ -1327,7 +1337,7 @@ public class DevicePolicyManager {
            CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER, CODE_HAS_PAIRED,
            CODE_MANAGED_USERS_NOT_SUPPORTED, CODE_SYSTEM_USER, CODE_CANNOT_ADD_MANAGED_PROFILE,
            CODE_NOT_SYSTEM_USER_SPLIT, CODE_DEVICE_ADMIN_NOT_SUPPORTED,
            CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER})
            CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER, CODE_ADD_MANAGED_PROFILE_DISALLOWED})
    public @interface ProvisioningPreCondition {}

    /**
@@ -6184,34 +6194,40 @@ public class DevicePolicyManager {
    }

    /**
     * Returns if provisioning a managed profile or device is possible or not.
     * Returns whether it is possible for the caller to initiate provisioning of a managed profile
     * or device, setting itself as the device or profile owner.
     *
     * @param action One of {@link #ACTION_PROVISION_MANAGED_DEVICE},
     * {@link #ACTION_PROVISION_MANAGED_PROFILE}.
     * @return if provisioning a managed profile or device is possible or not.
     * @return whether provisioning a managed profile or device is possible.
     * @throws IllegalArgumentException if the supplied action is not valid.
     */
    public boolean isProvisioningAllowed(String action) {
    public boolean isProvisioningAllowed(@NonNull String action) {
        throwIfParentInstance("isProvisioningAllowed");
        try {
            return mService.isProvisioningAllowed(action);
            return mService.isProvisioningAllowed(action, mContext.getPackageName());
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Checks if provisioning a managed profile or device is possible and returns one of the
     * {@link ProvisioningPreCondition}.
     * Checks whether it is possible to initiate provisioning a managed device,
     * profile or user, setting the given package as owner.
     *
     * @param action One of {@link #ACTION_PROVISION_MANAGED_DEVICE},
     *        {@link #ACTION_PROVISION_MANAGED_PROFILE},
     *        {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE},
     *        {@link #ACTION_PROVISION_MANAGED_USER}
     * @param packageName The package of the component that would be set as device, user, or profile
     *        owner.
     * @return A {@link ProvisioningPreCondition} value indicating whether provisioning is allowed.
     * @hide
     */
    public @ProvisioningPreCondition int checkProvisioningPreCondition(String action) {
    public @ProvisioningPreCondition int checkProvisioningPreCondition(
            String action, @NonNull String packageName) {
        try {
            return mService.checkProvisioningPreCondition(action);
            return mService.checkProvisioningPreCondition(action, packageName);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
@@ -6940,8 +6956,8 @@ public class DevicePolicyManager {
     * @hide
     * Force update user setup completed status. This API has no effect on user build.
     * @throws {@link SecurityException} if the caller has no
     *         {@link android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS} or the caller is
     *         not {@link UserHandle.SYSTEM_USER}
     *         {@code android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS} or the caller is
     *         not {@link UserHandle#SYSTEM_USER}
     */
    public void forceUpdateUserSetupComplete() {
        try {
+2 −2
Original line number Diff line number Diff line
@@ -269,8 +269,8 @@ interface IDevicePolicyManager {
    boolean setPermissionGrantState(in ComponentName admin, String packageName,
            String permission, int grantState);
    int getPermissionGrantState(in ComponentName admin, String packageName, String permission);
    boolean isProvisioningAllowed(String action);
    int checkProvisioningPreCondition(String action);
    boolean isProvisioningAllowed(String action, String packageName);
    int checkProvisioningPreCondition(String action, String packageName);
    void setKeepUninstalledPackages(in ComponentName admin,in List<String> packageList);
    List<String> getKeepUninstalledPackages(in ComponentName admin);
    boolean isManagedProfile(in ComponentName admin);
+54 −28
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.devicepolicy;

import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED;
import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.CODE_HAS_DEVICE_OWNER;
@@ -1689,9 +1690,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

        mSecurityLogMonitor = new SecurityLogMonitor(this);

        mHasFeature = mContext.getPackageManager()
        mHasFeature = mInjector.getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
        mIsWatch = mContext.getPackageManager()
        mIsWatch = mInjector.getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_WATCH);
        if (!mHasFeature) {
            // Skip the rest of the initialization
@@ -4460,7 +4461,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }

            try {
                int uid = mContext.getPackageManager().getPackageUidAsUser(
                int uid = mInjector.getPackageManager().getPackageUidAsUser(
                        policy.mDelegatedCertInstallerPackage, userHandle);
                return uid == callingUid;
            } catch (NameNotFoundException e) {
@@ -6021,6 +6022,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    private boolean isDeviceOwnerPackage(String packageName, int userId) {
        synchronized (this) {
            return mOwners.hasDeviceOwner()
                    && mOwners.getDeviceOwnerUserId() == userId
                    && mOwners.getDeviceOwnerPackageName().equals(packageName);
        }
    }

    public boolean isProfileOwner(ComponentName who, int userId) {
        final ComponentName profileOwner = getProfileOwner(userId);
        return who != null && who.equals(profileOwner);
@@ -6103,7 +6112,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        Preconditions.checkNotNull(packageName, "packageName is null");
        final int callingUid = mInjector.binderGetCallingUid();
        try {
            int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
            int uid = mInjector.getPackageManager().getPackageUidAsUser(packageName,
                    UserHandle.getUserId(callingUid));
            if (uid != callingUid) {
                throw new SecurityException("Invalid packageName");
@@ -6847,7 +6856,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }

            try {
                int uid = mContext.getPackageManager().getPackageUidAsUser(
                int uid = mInjector.getPackageManager().getPackageUidAsUser(
                        policy.mApplicationRestrictionsManagingPackage, userHandle);
                return uid == callingUid;
            } catch (NameNotFoundException e) {
@@ -8635,7 +8644,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            final String deviceOwnerPackageName = mOwners.getDeviceOwnerComponent()
                    .getPackageName();
            final String[] pkgs = mContext.getPackageManager().getPackagesForUid(callerUid);
            final String[] pkgs = mInjector.getPackageManager().getPackagesForUid(callerUid);

            for (String pkg : pkgs) {
                if (deviceOwnerPackageName.equals(pkg)) {
@@ -8672,7 +8681,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

            ActivityInfo[] receivers = null;
            try {
                receivers  = mContext.getPackageManager().getPackageInfo(
                receivers  = mInjector.getPackageManager().getPackageInfo(
                        deviceOwnerPackage, PackageManager.GET_RECEIVERS).receivers;
            } catch (NameNotFoundException e) {
                Log.e(LOG_TAG, "Cannot find device owner package", e);
@@ -8728,7 +8737,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                        < android.os.Build.VERSION_CODES.M) {
                    return false;
                }
                final PackageManager packageManager = mContext.getPackageManager();
                final PackageManager packageManager = mInjector.getPackageManager();
                switch (grantState) {
                    case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
                        mInjector.getPackageManagerInternal().grantRuntimePermission(packageName,
@@ -8763,7 +8772,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    @Override
    public int getPermissionGrantState(ComponentName admin, String packageName,
            String permission) throws RemoteException {
        PackageManager packageManager = mContext.getPackageManager();
        PackageManager packageManager = mInjector.getPackageManager();

        UserHandle user = mInjector.binderGetCallingUserHandle();
        synchronized (this) {
@@ -8800,17 +8809,33 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }

    @Override
    public boolean isProvisioningAllowed(String action) {
        return checkProvisioningPreConditionSkipPermission(action) == CODE_OK;
    public boolean isProvisioningAllowed(String action, String packageName) {
        Preconditions.checkNotNull(packageName);

        final int callingUid = mInjector.binderGetCallingUid();
        final long ident = mInjector.binderClearCallingIdentity();
        try {
            final int uidForPackage = mInjector.getPackageManager().getPackageUidAsUser(
                    packageName, UserHandle.getUserId(callingUid));
            Preconditions.checkArgument(callingUid == uidForPackage,
                    "Caller uid doesn't match the one for the provided package.");
        } catch (NameNotFoundException e) {
            throw new IllegalArgumentException("Invalid package provided " + packageName, e);
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
        }

        return checkProvisioningPreConditionSkipPermission(action, packageName) == CODE_OK;
    }

    @Override
    public int checkProvisioningPreCondition(String action) {
    public int checkProvisioningPreCondition(String action, String packageName) {
        Preconditions.checkNotNull(packageName);
        enforceCanManageProfileAndDeviceOwners();
        return checkProvisioningPreConditionSkipPermission(action);
        return checkProvisioningPreConditionSkipPermission(action, packageName);
    }

    private int checkProvisioningPreConditionSkipPermission(String action) {
    private int checkProvisioningPreConditionSkipPermission(String action, String packageName) {
        if (!mHasFeature) {
            return CODE_DEVICE_ADMIN_NOT_SUPPORTED;
        }
@@ -8819,7 +8844,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        if (action != null) {
            switch (action) {
                case DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE:
                    return checkManagedProfileProvisioningPreCondition(callingUserId);
                    return checkManagedProfileProvisioningPreCondition(packageName, callingUserId);
                case DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE:
                    return checkDeviceOwnerProvisioningPreCondition(callingUserId);
                case DevicePolicyManager.ACTION_PROVISION_MANAGED_USER:
@@ -8888,7 +8913,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    private int checkManagedProfileProvisioningPreCondition(int callingUserId) {
    private int checkManagedProfileProvisioningPreCondition(String packageName, int callingUserId) {
        if (!hasFeatureManagedUsers()) {
            return CODE_MANAGED_USERS_NOT_SUPPORTED;
        }
@@ -8901,24 +8926,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            // Managed user cannot have a managed profile.
            return CODE_USER_HAS_PROFILE_OWNER;
        }

        final long ident = mInjector.binderClearCallingIdentity();
        try {
             /* STOPSHIP(b/31952368) Reinstate a check similar to this once ManagedProvisioning
                   uses checkProvisioningPreCondition (see ag/1607846) and passes the packageName
                   there. In isProvisioningAllowed we should check isCallerDeviceOwner, but for
                   managed provisioning we need to check the package that is going to be set as PO
                if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE)) {
                    if (!isCallerDeviceOwner(callingUid)
            final UserHandle callingUserHandle = UserHandle.of(callingUserId);
            if (mUserManager.hasUserRestriction(
                    UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserHandle)) {
                // The DO can initiate provisioning if the restriction was set by the DO.
                if (!isDeviceOwnerPackage(packageName, callingUserId)
                        || isAdminAffectedByRestriction(mOwners.getDeviceOwnerComponent(),
                                UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserId)) {
                    // Caller is not DO or the restriction was set by the system.
                    return false;
                    return CODE_ADD_MANAGED_PROFILE_DISALLOWED;
                }
                } */
            }

            // TODO: Allow it if the caller is the DO? DO could just call removeUser() before
            // provisioning, so not strictly required...
            boolean canRemoveProfile = !mUserManager.hasUserRestriction(
                        UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, UserHandle.of(callingUserId));
                        UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, callingUserHandle);
            if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) {
                return CODE_CANNOT_ADD_MANAGED_PROFILE;
            }
+130 −15

File changed.

Preview size limit exceeded, changes collapsed.

+4 −0
Original line number Diff line number Diff line
@@ -82,6 +82,10 @@ public abstract class DpmTestBase extends AndroidTestCase {
                eq(packageName),
                eq(0),
                eq(userId));

        doReturn(ai.uid).when(mMockContext.packageManager).getPackageUidAsUser(
                eq(packageName),
                eq(userId));
    }

    protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid)