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:
@@ -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())) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user