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

Commit 7d0becbc authored by Eran Messeri's avatar Eran Messeri
Browse files

Remove DO/PO "policy" from DeviceAdminInfo

Remove the USES_POLICY_DEVICE_OWNER and USES_POLICY_PROFILE_OWNER from
DeviceAdminInfo, and all the code referring to these constants.

This is to prevent callers calling getActiveAdminXXX variants which
take in the DO/PO constant, leading them to use getDeviceOwnerLocked,
getProfileOwnerLocked, etc.

The USES_POLICY_PROFILE_OWNER constant was particularly confusing because
it implied Device Owner was also acceptable for this "policy", which
was plain wrong in some cases.

Bug: 163028934
Test: atest FrameworksServicesTests:DevicePolicyManagerTest
Test: atest com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest com.android.cts.devicepolicy.MixedDeviceOwnerTest com.android.cts.devicepolicy.MixedProfileOwnerTest
Change-Id: Ie78bb8a1948f29ac440f220e14f71b8a0f7f32e1
parent 30ae7a43
Loading
Loading
Loading
Loading
+0 −16
Original line number Diff line number Diff line
@@ -54,22 +54,6 @@ import java.util.HashMap;
public final class DeviceAdminInfo implements Parcelable {
    static final String TAG = "DeviceAdminInfo";

    /**
     * A type of policy that this device admin can use: device owner meta-policy
     * for an admin that is designated as owner of the device.
     *
     * @hide
     */
    public static final int USES_POLICY_DEVICE_OWNER = -2;

    /**
     * A type of policy that this device admin can use: profile owner meta-policy
     * for admins that have been installed as owner of some user profile.
     *
     * @hide
     */
    public static final int USES_POLICY_PROFILE_OWNER = -1;

    /**
     * A type of policy that this device admin can use: limit the passwords
     * that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
+62 −72
Original line number Diff line number Diff line
@@ -1646,6 +1646,29 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        return getCallerIdentity(callerPackage);
    }
    /**
     * Creates a new {@link CallerIdentity} object to represent the caller's identity.
     * If an {@code adminComponent} is specified, then the caller must be an admin and
     * the provided component name must match the caller's UID.
     *
     * If a package name is provided, then the caller doesn't have to be an admin, and the
     * provided package must belong to the caller's UID.
     *
     * If neither is provided, the caller identity is returned as-is.
     *
     * Note: this method should only be called when the caller may not be an admin. If the caller
     * is not an admin, the ComponentName in the returned identity will be null.
     */
    private CallerIdentity getNonPrivilegedOrAdminCallerIdentity(
            @Nullable ComponentName adminComponent,
            @Nullable String callerPackage) {
        if (adminComponent != null) {
            return getCallerIdentity(adminComponent);
        }
        return getNonPrivilegedOrAdminCallerIdentityUsingPackage(callerPackage);
    }
    /**
     * Retrieves the active admin of the caller. This method should not be called directly and
     * should only be called by {@link #getAdminCallerIdentity},
@@ -2313,14 +2336,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            final boolean isDeviceOwner = isDeviceOwner(admin.info.getComponent(), userId);
            final boolean isProfileOwner = isProfileOwner(admin.info.getComponent(), userId);
            if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
                throw new SecurityException("Admin " + admin.info.getComponent()
                        + " does not own the device");
            }
            if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
                throw new SecurityException("Admin " + admin.info.getComponent()
                        + " does not own the profile");
            }
            if (DA_DISALLOWED_POLICIES.contains(reqPolicy) && !isDeviceOwner && !isProfileOwner) {
                throw new SecurityException("Admin " + admin.info.getComponent()
                        + " is not a device owner or profile owner, so may not use policy: "
@@ -2426,21 +2441,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        ensureLocked();
        final boolean ownsDevice = isDeviceOwner(admin.info.getComponent(), userId);
        final boolean ownsProfile = isProfileOwner(admin.info.getComponent(), userId);
        final boolean ownsProfileOnOrganizationOwnedDevice =
                    isProfileOwnerOfOrganizationOwnedDevice(admin.info.getComponent(), userId);
        if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
            return ownsDevice;
        } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
            // DO always has the PO power.
            return ownsDevice || ownsProfileOnOrganizationOwnedDevice || ownsProfile;
        } else {
        boolean allowedToUsePolicy = ownsDevice || ownsProfile
                || !DA_DISALLOWED_POLICIES.contains(reqPolicy)
                || getTargetSdk(admin.info.getPackageName(), userId) < Build.VERSION_CODES.Q;
        return allowedToUsePolicy && admin.info.usesPolicy(reqPolicy);
    }
    }
    void sendAdminCommandLocked(ActiveAdmin admin, String action) {
        sendAdminCommandLocked(admin, action, null);
@@ -5486,22 +5492,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    public List<String> getDelegatedScopes(ComponentName who,
            String delegatePackage) throws SecurityException {
        Objects.requireNonNull(delegatePackage, "Delegate package is null");
        final CallerIdentity caller = getNonPrivilegedOrAdminCallerIdentity(who, delegatePackage);
        // Retrieve the user ID of the calling process.
        final int callingUid = mInjector.binderGetCallingUid();
        final int userId = UserHandle.getUserId(callingUid);
        // Ensure the caller may call this method:
        // * Either it's an admin
        // * Or it's an app identified by its calling package name (the
        // getNonPrivilegedOrAdminCallerIdentity method validated the UID and package match).
        Preconditions.checkCallAuthorization(
                (caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller)))
                || delegatePackage != null);
        synchronized (getLockObject()) {
            // Ensure calling process is device/profile owner.
            if (who != null) {
                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
            // Or ensure calling process is delegatePackage itself.
            } else {
                if (!isCallingFromPackage(delegatePackage, callingUid)) {
                    throw new SecurityException("Caller with uid " + callingUid + " is not "
                            + delegatePackage);
                }
            }
            final DevicePolicyData policy = getUserData(userId);
            final DevicePolicyData policy = getUserData(caller.getUserId());
            // Retrieve the scopes assigned to delegatePackage, or null if no scope was given.
            final List<String> scopes = policy.mDelegationMap.get(delegatePackage);
            return scopes == null ? Collections.EMPTY_LIST : scopes;
@@ -8359,38 +8360,28 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    private void enforceDeviceOwnerOrManageUsers() {
        synchronized (getLockObject()) {
            if (getActiveAdminWithPolicyForUidLocked(null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
                    mInjector.binderGetCallingUid()) != null) {
        final CallerIdentity caller = getCallerIdentity();
        if (isDeviceOwner(caller)) {
            return;
        }
        }
        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
        Preconditions.checkCallAuthorization(canManageUsers(caller));
    }
    private void enforceProfileOwnerOrSystemUser() {
        synchronized (getLockObject()) {
            if (getActiveAdminWithPolicyForUidLocked(null,
                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid())
                            != null) {
        final CallerIdentity caller = getCallerIdentity();
        if (isDeviceOwner(caller) || isProfileOwner(caller)) {
            return;
        }
        }
        Preconditions.checkState(isCallerWithSystemUid(),
        Preconditions.checkState(isSystemUid(caller),
                "Only profile owner, device owner and system may call this method.");
    }
    private void enforceProfileOwnerOrFullCrossUsersPermission(CallerIdentity caller,
            int userId) {
        if (userId == caller.getUserId()) {
            synchronized (getLockObject()) {
                if (getActiveAdminWithPolicyForUidLocked(null,
                        DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, caller.getUid()) != null) {
        if ((userId == caller.getUserId()) && (isProfileOwner(caller) || isDeviceOwner(caller))) {
            // Device Owner/Profile Owner may access the user it runs on.
            return;
        }
            }
        }
        Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
    }
@@ -9282,10 +9273,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            throw new IllegalArgumentException("profileOwner " + profileOwner + " and admin "
                    + admin + " are not in the same package");
        }
        final CallerIdentity caller = getCallerIdentity(admin);
        // Only allow the system user to use this method
        if (!mInjector.binderGetCallingUserHandle().isSystem()) {
            throw new SecurityException("createAndManageUser was called from non-system user");
        }
        Preconditions.checkCallAuthorization(caller.getUserHandle().isSystem(),
                "createAndManageUser was called from non-system user");
        Preconditions.checkCallAuthorization(isDeviceOwner(caller));
        final boolean ephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0;
        final boolean demo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0
                && UserManager.isDeviceInDemoMode(mContext);
@@ -9295,8 +9287,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        // Create user.
        UserHandle user = null;
        synchronized (getLockObject()) {
            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
            final int callingUid = mInjector.binderGetCallingUid();
            final long id = mInjector.binderClearCallingIdentity();
            try {
@@ -11158,25 +11148,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        @Override
        public boolean isActiveDeviceOwner(int uid) {
            synchronized (getLockObject()) {
                return getActiveAdminWithPolicyForUidLocked(
                        null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER, uid) != null;
            }
            return isDeviceOwner(new CallerIdentity(uid, null, null));
        }
        @Override
        public boolean isActiveProfileOwner(int uid) {
            synchronized (getLockObject()) {
                return getActiveAdminWithPolicyForUidLocked(
                        null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, uid) != null;
            }
            return isProfileOwner(new CallerIdentity(uid, null, null));
        }
        @Override
        public boolean isActiveSupervisionApp(int uid) {
            if (!isProfileOwner(new CallerIdentity(uid, null, null))) {
                return false;
            }
            synchronized (getLockObject()) {
                final ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
                        null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, uid);
                final ActiveAdmin admin = getProfileOwnerAdminLocked(UserHandle.getUserId(uid));
                if (admin == null) {
                    return false;
                }
@@ -11702,6 +11688,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                .getPackageName();
        try {
            String[] pkgs = mInjector.getIPackageManager().getPackagesForUid(appUid);
            if (pkgs == null) {
                return false;
            }
            for (String pkg : pkgs) {
                if (deviceOwnerPackageName.equals(pkg)) {
                    return true;