diff options
3 files changed, 60 insertions, 38 deletions
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java index 5fbe5b398488..cae3cf5b44c3 100644 --- a/core/java/android/app/admin/DeviceAdminInfo.java +++ b/core/java/android/app/admin/DeviceAdminInfo.java @@ -73,12 +73,10 @@ public final class DeviceAdminInfo implements Parcelable { * that the user can select, via {@link DevicePolicyManager#setPasswordQuality} * and {@link DevicePolicyManager#setPasswordMinimumLength}. * - * <p>To control this policy, the device admin must have a "limit-password" - * tag in the "uses-policies" section of its meta-data. - * - * <p>This policy is deprecated for use by a device admin. In future releases, it will - * only be possible for a device owner or profile owner to enforce constraints on user - * passwords. + * <p>To control this policy, the device admin must be a device owner or profile owner, + * and must have a "limit-password" tag in the "uses-policies" section of its meta-data. + * If used by a device owner, the policy only affects the primary user and its profiles, + * but not any secondary users on the device. */ public static final int USES_POLICY_LIMIT_PASSWORD = 0; @@ -138,11 +136,10 @@ public final class DeviceAdminInfo implements Parcelable { * A type of policy that this device admin can use: force the user to * change their password after an administrator-defined time limit. * - * <p>To control this policy, the device admin must have an "expire-password" - * tag in the "uses-policies" section of its meta-data. - * - * <p>This policy is deprecated for use by a device admin. In future releases, it will - * only be possible for a device owner or profile owner to enforce password expiry. + * <p>To control this policy, the device admin must be a device owner or profile owner, + * and must have an "expire-password" tag in the "uses-policies" section of its meta-data. + * If used by a device owner, the policy only affects the primary user and its profiles, + * but not any secondary users on the device. */ public static final int USES_POLICY_EXPIRE_PASSWORD = 6; @@ -157,23 +154,19 @@ public final class DeviceAdminInfo implements Parcelable { /** * A type of policy that this device admin can use: disables use of all device cameras. * - * <p>To control this policy, the device admin must have a "disable-camera" - * tag in the "uses-policies" section of its meta-data. - * - * <p>This policy is deprecated for use by a device admin. In future releases, it will - * only be possible for a device owner or profile owner to disable use of the camera. + * <p>To control this policy, the device admin must be a device owner or profile owner, + * and must have a "disable-camera" tag in the "uses-policies" section of its meta-data. + * If used by a device owner, the policy affects all users on the device. */ public static final int USES_POLICY_DISABLE_CAMERA = 8; /** * A type of policy that this device admin can use: disables use of keyguard features. * - * <p>To control this policy, the device admin must have a "disable-keyguard-features" - * tag in the "uses-policies" section of its meta-data. - * - * <p>This policy is deprecated for use by a device admin. In future releases, it will - * only be possible for a device owner or profile owner to disable use of keyguard - * features. + * <p>To control this policy, the device admin must be a device owner or profile owner, + * and must have a "disable-keyguard-features" tag in the "uses-policies" section of its + * meta-data. If used by a device owner, the policy only affects the primary user and + * its profiles, but not any secondary users on the device. */ public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 81ac6a40e88a..1ea1a9e6c6e6 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -377,6 +377,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private static final Set<String> GLOBAL_SETTINGS_WHITELIST; private static final Set<String> GLOBAL_SETTINGS_DEPRECATED; private static final Set<String> SYSTEM_SETTINGS_WHITELIST; + private static final Set<Integer> DA_DISALLOWED_POLICIES; static { SECURE_SETTINGS_WHITELIST = new ArraySet<>(); SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD); @@ -408,6 +409,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS); SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS_MODE); SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_OFF_TIMEOUT); + + DA_DISALLOWED_POLICIES = new ArraySet<>(); + DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA); + DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES); + DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD); + DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); } /** @@ -2607,6 +2614,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final int userId = UserHandle.getUserId(callingUid); final DevicePolicyData policy = getUserData(userId); ActiveAdmin admin = policy.mAdminMap.get(who); + 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"); @@ -2615,6 +2625,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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: " + + admin.info.getTagForPolicy(reqPolicy)); + } throw new SecurityException("Admin " + admin.info.getComponent() + " did not specify uses-policy for: " + admin.info.getTagForPolicy(reqPolicy)); @@ -2694,7 +2709,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // DO always has the PO power. return ownsDevice || ownsProfile; } else { - return admin.info.usesPolicy(reqPolicy); + boolean allowedToUsePolicy = ownsDevice || ownsProfile + || !DA_DISALLOWED_POLICIES.contains(reqPolicy) + || getTargetSdk(admin.info.getPackageName(), userId) < Build.VERSION_CODES.Q; + return allowedToUsePolicy && admin.info.usesPolicy(reqPolicy); } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index a23636ca20dc..5da2a8548fb3 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -1713,24 +1713,35 @@ public class DevicePolicyManagerTest extends DpmTestBase { UserManager.DISALLOW_ADD_USER), eq(true), eq(CAMERA_DISABLED_GLOBALLY)); reset(getServices().userManagerInternal); + } - // Set up another DA and let it disable camera. Now DISALLOW_CAMERA will only be applied - // locally. - dpm.setCameraDisabled(admin1, false); - reset(getServices().userManagerInternal); + public void testDaDisallowedPolicies_SecurityException() throws Exception { + mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); + mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL); - setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_SYSTEM_USER_UID); - dpm.setActiveAdmin(admin2, /* replace =*/ false, UserHandle.USER_SYSTEM); - dpm.setCameraDisabled(admin2, true); + setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID); + dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM); - verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( - eq(UserHandle.USER_SYSTEM), - // DISALLOW_CAMERA will be applied to both local and global. <- TODO: fix this - MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN, - UserManager.DISALLOW_ADD_USER), - eq(true), eq(CAMERA_DISABLED_LOCALLY)); - reset(getServices().userManagerInternal); - // TODO Make sure restrictions are written to the file. + boolean originalCameraDisabled = dpm.getCameraDisabled(admin1); + assertExpectException(SecurityException.class, /* messageRegex= */ null, + () -> dpm.setCameraDisabled(admin1, true)); + assertEquals(originalCameraDisabled, dpm.getCameraDisabled(admin1)); + + int originalKeyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(admin1); + assertExpectException(SecurityException.class, /* messageRegex= */ null, + () -> dpm.setKeyguardDisabledFeatures(admin1, + DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)); + assertEquals(originalKeyguardDisabledFeatures, dpm.getKeyguardDisabledFeatures(admin1)); + + long originalPasswordExpirationTimeout = dpm.getPasswordExpirationTimeout(admin1); + assertExpectException(SecurityException.class, /* messageRegex= */ null, + () -> dpm.setPasswordExpirationTimeout(admin1, 1234)); + assertEquals(originalPasswordExpirationTimeout, dpm.getPasswordExpirationTimeout(admin1)); + + int originalPasswordQuality = dpm.getPasswordQuality(admin1); + assertExpectException(SecurityException.class, /* messageRegex= */ null, + () -> dpm.setPasswordQuality(admin1, DevicePolicyManager.PASSWORD_QUALITY_NUMERIC)); + assertEquals(originalPasswordQuality, dpm.getPasswordQuality(admin1)); } public void testSetUserRestriction_asPo() { |