Don't use user restriction permission checks for DPC admins

Bug: 273494642
Bug: 272058962
Test: btest c.a.c.d.UserRestrictionsTest
Test: btest a.d.c.TelephonyTest
Test: btest a.d.c.InstallUnknownSourcesTest
Test: btest a.d.c.UserRestrictionsTest
Change-Id: I76a7279702812ae0e3fb4fae4d2e46b57333f2d3
This commit is contained in:
Kholoud Mohamed
2023-04-11 09:21:11 +00:00
parent a38aeb81a8
commit 020e703497
3 changed files with 100 additions and 66 deletions

View File

@@ -699,7 +699,7 @@ final class DevicePolicyEngine {
if (policyDefinition.isGlobalOnlyPolicy()) {
throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a global only"
+ "policy.");
+ " policy.");
}
if (!mLocalPolicies.contains(userId)) {
@@ -724,7 +724,7 @@ final class DevicePolicyEngine {
private <V> PolicyState<V> getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
if (policyDefinition.isLocalOnlyPolicy()) {
throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a local only"
+ "policy.");
+ " policy.");
}
if (!mGlobalPolicies.containsKey(policyDefinition.getPolicyKey())) {

View File

@@ -441,7 +441,6 @@ import android.util.AtomicFile;
import android.util.DebugUtils;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -13131,19 +13130,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
int userId = caller.getUserId();
if (!UserRestrictionsUtils.isValidRestriction(key)) {
return;
}
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION);
if (isPolicyEngineForFinanceFlagEnabled()) {
int affectedUserId = parent ? getProfileParentId(userId) : userId;
EnforcingAdmin admin = enforcePermissionForUserRestriction(
who,
key,
caller.getPackageName(),
affectedUserId);
if (mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, callerPackage, userId)) {
if (!isDeviceOwner(caller) && !isProfileOwner(caller)) {
if (!mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, callerPackage, userId)) {
throw new IllegalStateException("Calling package is not targeting Android U.");
}
if (!UserRestrictionsUtils.isValidRestriction(key)) {
throw new IllegalArgumentException("Invalid restriction key: " + key);
}
int affectedUserId = parent ? getProfileParentId(userId) : userId;
EnforcingAdmin admin = enforcePermissionForUserRestriction(
who,
key,
caller.getPackageName(),
affectedUserId);
PolicyDefinition<Boolean> policyDefinition =
PolicyDefinition.getPolicyDefinitionForUserRestriction(key);
if (enabledFromThisOwner) {
@@ -13155,7 +13157,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
setGlobalUserRestrictionInternal(admin, key, /* enabled= */ false);
}
if (!policyDefinition.isGlobalOnlyPolicy()) {
setLocalUserRestrictionInternal(admin, key, /* enabled= */ false, userId);
setLocalUserRestrictionInternal(admin, key, /* enabled= */ false,
userId);
int parentUserId = getProfileParentId(userId);
if (parentUserId != userId) {
@@ -13165,49 +13168,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
} else {
if (!UserRestrictionsUtils.isValidRestriction(key)) {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackage);
checkAdminCanSetRestriction(caller, parent, key);
setBackwardCompatibleUserRestriction(
caller, admin, key, enabledFromThisOwner, parent);
}
} else {
if (!UserRestrictionsUtils.isValidRestriction(key)) {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
if (parent) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller));
} else {
Preconditions.checkCallAuthorization(
isDeviceOwner(caller) || isProfileOwner(caller));
}
synchronized (getLockObject()) {
if (isDefaultDeviceOwner(caller)) {
if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
throw new SecurityException("Device owner cannot set user restriction "
+ key);
}
Preconditions.checkArgument(!parent,
"Cannot use the parent instance in Device Owner mode");
} else if (isFinancedDeviceOwner(caller)) {
if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(key)) {
throw new SecurityException("Cannot set user restriction " + key
+ " when managing a financed device");
}
Preconditions.checkArgument(!parent,
"Cannot use the parent instance in Financed Device Owner"
+ " mode");
} else {
boolean profileOwnerCanChangeOnItself = !parent
&& UserRestrictionsUtils.canProfileOwnerChange(
key, userId == getMainUserId());
boolean orgOwnedProfileOwnerCanChangeGlobally = parent
&& isProfileOwnerOfOrganizationOwnedDevice(caller)
&& UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(
key);
if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) {
throw new SecurityException("Profile owner cannot set user restriction "
+ key);
}
}
}
checkAdminCanSetRestriction(caller, parent, key);
synchronized (getLockObject()) {
final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
getProfileOwnerOrDeviceOwnerLocked(userId), parent);
@@ -13224,6 +13199,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
logUserRestrictionCall(key, enabledFromThisOwner, parent, caller);
}
private void checkAdminCanSetRestriction(CallerIdentity caller, boolean parent, String key) {
if (parent) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller));
} else {
Preconditions.checkCallAuthorization(
isDeviceOwner(caller) || isProfileOwner(caller));
}
synchronized (getLockObject()) {
if (isDefaultDeviceOwner(caller)) {
if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
throw new SecurityException("Device owner cannot set user restriction "
+ key);
}
Preconditions.checkArgument(!parent,
"Cannot use the parent instance in Device Owner mode");
} else if (isFinancedDeviceOwner(caller)) {
if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(key)) {
throw new SecurityException("Cannot set user restriction " + key
+ " when managing a financed device");
}
Preconditions.checkArgument(!parent,
"Cannot use the parent instance in Financed Device Owner"
+ " mode");
} else {
boolean profileOwnerCanChangeOnItself = !parent
&& UserRestrictionsUtils.canProfileOwnerChange(
key, caller.getUserId() == getMainUserId());
boolean orgOwnedProfileOwnerCanChangeGlobally = parent
&& isProfileOwnerOfOrganizationOwnedDevice(caller)
&& UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(
key);
if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) {
throw new SecurityException("Profile owner cannot set user restriction "
+ key);
}
}
}
}
private void setBackwardCompatibleUserRestriction(
CallerIdentity caller, EnforcingAdmin admin, String key, boolean enabled,
boolean parent) {
@@ -13252,20 +13267,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void setUserRestrictionGlobally(String callerPackage, String key) {
final CallerIdentity caller = getCallerIdentity(callerPackage);
if (!UserRestrictionsUtils.isValidRestriction(key)) {
return;
}
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION);
if (!isPolicyEngineForFinanceFlagEnabled()) {
throw new IllegalStateException("Feature flag is not enabled.");
}
if (isDeviceOwner(caller) || isProfileOwner(caller)) {
throw new IllegalStateException("Admins are not allowed to call this API.");
}
if (!mInjector.isChangeEnabled(
ENABLE_COEXISTENCE_CHANGE, callerPackage, caller.getUserId())) {
throw new IllegalStateException("Calling package is not targeting Android U.");
}
if (!UserRestrictionsUtils.isValidRestriction(key)) {
throw new IllegalArgumentException("Invalid restriction key: " + key);
}
EnforcingAdmin admin = enforcePermissionForUserRestriction(
/* who= */ null,
@@ -13416,14 +13433,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int targetUserId = parent
? getProfileParentId(caller.getUserId()) : caller.getUserId();
EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackage);
Bundle restrictions = getUserRestrictionsFromPolicyEngine(admin, targetUserId);
// Add global restrictions set by the admin as well if admin is not targeting Android U.
if (!mInjector.isChangeEnabled(
ENABLE_COEXISTENCE_CHANGE, callerPackage, caller.getUserId())) {
if (isDeviceOwner(caller) || isProfileOwner(caller)) {
Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
|| isFinancedDeviceOwner(caller)
|| isProfileOwner(caller)
|| (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
Bundle restrictions = getUserRestrictionsFromPolicyEngine(admin, targetUserId);
// Add global restrictions set by the admin as well.
restrictions.putAll(
getUserRestrictionsFromPolicyEngine(admin, UserHandle.USER_ALL));
return restrictions;
} else {
if (!mInjector.isChangeEnabled(
ENABLE_COEXISTENCE_CHANGE, callerPackage, caller.getUserId())) {
throw new IllegalStateException("Calling package is not targeting Android U.");
}
return getUserRestrictionsFromPolicyEngine(admin, targetUserId);
}
return restrictions;
} else {
Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)

View File

@@ -284,6 +284,7 @@ final class PolicyDefinition<V> {
private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>();
private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>();
// TODO(b/277218360): Revisit policies that should be marked as global-only.
static {
POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY, AUTO_TIMEZONE);
POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMISSION_GRANT_POLICY,
@@ -312,8 +313,9 @@ final class PolicyDefinition<V> {
USER_RESTRICTION_FLAGS.put(
UserManager.DISALLOW_WIFI_TETHERING, POLICY_FLAG_GLOBAL_ONLY_POLICY);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_GRANT_ADMIN, /* flags= */ 0);
// TODO: set as global only once we get rid of the mapping
USER_RESTRICTION_FLAGS.put(
UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, POLICY_FLAG_GLOBAL_ONLY_POLICY);
UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(
UserManager.DISALLOW_WIFI_DIRECT, POLICY_FLAG_GLOBAL_ONLY_POLICY);
USER_RESTRICTION_FLAGS.put(
@@ -333,8 +335,10 @@ final class PolicyDefinition<V> {
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_BLUETOOTH, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BLUETOOTH, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BLUETOOTH_SHARING, /* flags= */ 0);
// This effectively always applies globally, but it can be set on the profile
// parent, check the javadocs on the restriction for more info.
USER_RESTRICTION_FLAGS.put(
UserManager.DISALLOW_USB_FILE_TRANSFER, POLICY_FLAG_GLOBAL_ONLY_POLICY);
UserManager.DISALLOW_USB_FILE_TRANSFER, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_CREDENTIALS, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_REMOVE_USER, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, /* flags= */ 0);
@@ -344,8 +348,10 @@ final class PolicyDefinition<V> {
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_DATE_TIME, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(
UserManager.DISALLOW_CONFIG_TETHERING, /* flags= */ 0);
// This effectively always applies globally, but it can be set on the profile
// parent, check the javadocs on the restriction for more info.
USER_RESTRICTION_FLAGS.put(
UserManager.DISALLOW_NETWORK_RESET, POLICY_FLAG_GLOBAL_ONLY_POLICY);
UserManager.DISALLOW_NETWORK_RESET, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_FACTORY_RESET, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_USER, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_MANAGED_PROFILE, /* flags= */ 0);
@@ -376,8 +382,7 @@ final class PolicyDefinition<V> {
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNMUTE_DEVICE, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_DATA_ROAMING, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SET_USER_ICON, /* flags= */ 0);
// TODO: double check flags
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OEM_UNLOCK, POLICY_FLAG_GLOBAL_ONLY_POLICY);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OEM_UNLOCK, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNIFIED_PASSWORD, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.ALLOW_PARENT_PROFILE_APP_LINKING, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_AUTOFILL, /* flags= */ 0);
@@ -390,6 +395,7 @@ final class PolicyDefinition<V> {
USER_RESTRICTION_FLAGS.put(
UserManager.DISALLOW_CONFIG_PRIVATE_DNS, POLICY_FLAG_GLOBAL_ONLY_POLICY);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MICROPHONE_TOGGLE, /* flags= */ 0);
// TODO: According the UserRestrictionsUtils, this is global only, need to confirm.
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CAMERA_TOGGLE, /* flags= */ 0);
// TODO: check if its global only
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BIOMETRIC, /* flags= */ 0);