summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/AccountTypePolicyKey.java4
-rw-r--r--core/java/android/app/admin/BundlePolicyValue.java5
-rw-r--r--core/java/android/app/admin/ComponentNamePolicyValue.java5
-rw-r--r--core/java/android/app/admin/IntentFilterPolicyKey.java4
-rw-r--r--core/java/android/app/admin/LockTaskPolicy.java17
-rw-r--r--core/java/android/app/admin/PackagePermissionPolicyKey.java5
-rw-r--r--core/java/android/app/admin/PackagePolicyKey.java4
-rw-r--r--core/java/android/app/admin/PolicySizeVerifier.java128
-rw-r--r--core/java/android/app/admin/StringPolicyValue.java5
-rw-r--r--core/java/android/app/admin/StringSetPolicyValue.java7
-rw-r--r--core/java/android/app/admin/UserRestrictionPolicyKey.java4
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java41
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java91
13 files changed, 224 insertions, 96 deletions
diff --git a/core/java/android/app/admin/AccountTypePolicyKey.java b/core/java/android/app/admin/AccountTypePolicyKey.java
index 9e376a7e2bee..d81eb20512a2 100644
--- a/core/java/android/app/admin/AccountTypePolicyKey.java
+++ b/core/java/android/app/admin/AccountTypePolicyKey.java
@@ -19,6 +19,7 @@ package android.app.admin;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_ACCOUNT_TYPE;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_BUNDLE_KEY;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_KEY;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -53,6 +54,9 @@ public final class AccountTypePolicyKey extends PolicyKey {
@TestApi
public AccountTypePolicyKey(@NonNull String key, @NonNull String accountType) {
super(key);
+ if (devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxStringLength(accountType, "accountType");
+ }
mAccountType = Objects.requireNonNull((accountType));
}
diff --git a/core/java/android/app/admin/BundlePolicyValue.java b/core/java/android/app/admin/BundlePolicyValue.java
index f9653a4e85b0..cc5e75fac0ea 100644
--- a/core/java/android/app/admin/BundlePolicyValue.java
+++ b/core/java/android/app/admin/BundlePolicyValue.java
@@ -16,6 +16,8 @@
package android.app.admin;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
@@ -30,6 +32,9 @@ public final class BundlePolicyValue extends PolicyValue<Bundle> {
public BundlePolicyValue(Bundle value) {
super(value);
+ if (devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxParcelableFieldsLength(value);
+ }
}
private BundlePolicyValue(Parcel source) {
diff --git a/core/java/android/app/admin/ComponentNamePolicyValue.java b/core/java/android/app/admin/ComponentNamePolicyValue.java
index 635e5826e0c5..4d36195613ad 100644
--- a/core/java/android/app/admin/ComponentNamePolicyValue.java
+++ b/core/java/android/app/admin/ComponentNamePolicyValue.java
@@ -16,6 +16,8 @@
package android.app.admin;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
@@ -30,6 +32,9 @@ public final class ComponentNamePolicyValue extends PolicyValue<ComponentName> {
public ComponentNamePolicyValue(@NonNull ComponentName value) {
super(value);
+ if (devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxComponentNameLength(value);
+ }
}
private ComponentNamePolicyValue(Parcel source) {
diff --git a/core/java/android/app/admin/IntentFilterPolicyKey.java b/core/java/android/app/admin/IntentFilterPolicyKey.java
index 7526a7b2c934..de7ff9f0ad0f 100644
--- a/core/java/android/app/admin/IntentFilterPolicyKey.java
+++ b/core/java/android/app/admin/IntentFilterPolicyKey.java
@@ -19,6 +19,7 @@ package android.app.admin;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_INTENT_FILTER;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_BUNDLE_KEY;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_KEY;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -59,6 +60,9 @@ public final class IntentFilterPolicyKey extends PolicyKey {
@TestApi
public IntentFilterPolicyKey(@NonNull String identifier, @NonNull IntentFilter filter) {
super(identifier);
+ if (devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxParcelableFieldsLength(filter);
+ }
mFilter = Objects.requireNonNull(filter);
}
diff --git a/core/java/android/app/admin/LockTaskPolicy.java b/core/java/android/app/admin/LockTaskPolicy.java
index b671d5793803..9d6ce243a19b 100644
--- a/core/java/android/app/admin/LockTaskPolicy.java
+++ b/core/java/android/app/admin/LockTaskPolicy.java
@@ -16,6 +16,8 @@
package android.app.admin;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -75,7 +77,7 @@ public final class LockTaskPolicy extends PolicyValue<LockTaskPolicy> {
*/
public LockTaskPolicy(@Nullable Set<String> packages) {
if (packages != null) {
- mPackages.addAll(packages);
+ setPackagesInternal(packages);
}
setValue(this);
}
@@ -93,7 +95,7 @@ public final class LockTaskPolicy extends PolicyValue<LockTaskPolicy> {
*/
public LockTaskPolicy(@Nullable Set<String> packages, int flags) {
if (packages != null) {
- mPackages.addAll(packages);
+ setPackagesInternal(packages);
}
mFlags = flags;
setValue(this);
@@ -123,7 +125,7 @@ public final class LockTaskPolicy extends PolicyValue<LockTaskPolicy> {
*/
public void setPackages(@NonNull Set<String> packages) {
Objects.requireNonNull(packages);
- mPackages = new HashSet<>(packages);
+ setPackagesInternal(packages);
}
/**
@@ -133,6 +135,15 @@ public final class LockTaskPolicy extends PolicyValue<LockTaskPolicy> {
mFlags = flags;
}
+ private void setPackagesInternal(Set<String> packages) {
+ if (devicePolicySizeTrackingEnabled()) {
+ for (String p : packages) {
+ PolicySizeVerifier.enforceMaxPackageNameLength(p);
+ }
+ }
+ mPackages = new HashSet<>(packages);
+ }
+
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
diff --git a/core/java/android/app/admin/PackagePermissionPolicyKey.java b/core/java/android/app/admin/PackagePermissionPolicyKey.java
index 7fd514cebd7c..2241fddb7320 100644
--- a/core/java/android/app/admin/PackagePermissionPolicyKey.java
+++ b/core/java/android/app/admin/PackagePermissionPolicyKey.java
@@ -20,6 +20,7 @@ import static android.app.admin.PolicyUpdateReceiver.EXTRA_PACKAGE_NAME;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_PERMISSION_NAME;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_BUNDLE_KEY;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_KEY;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -58,6 +59,10 @@ public final class PackagePermissionPolicyKey extends PolicyKey {
public PackagePermissionPolicyKey(@NonNull String identifier, @NonNull String packageName,
@NonNull String permissionName) {
super(identifier);
+ if (devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxPackageNameLength(packageName);
+ PolicySizeVerifier.enforceMaxStringLength(permissionName, "permissionName");
+ }
mPackageName = Objects.requireNonNull((packageName));
mPermissionName = Objects.requireNonNull((permissionName));
}
diff --git a/core/java/android/app/admin/PackagePolicyKey.java b/core/java/android/app/admin/PackagePolicyKey.java
index 2ab00bc3146c..2ea17a18f6a6 100644
--- a/core/java/android/app/admin/PackagePolicyKey.java
+++ b/core/java/android/app/admin/PackagePolicyKey.java
@@ -19,6 +19,7 @@ package android.app.admin;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_PACKAGE_NAME;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_BUNDLE_KEY;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_KEY;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -54,6 +55,9 @@ public final class PackagePolicyKey extends PolicyKey {
@TestApi
public PackagePolicyKey(@NonNull String key, @NonNull String packageName) {
super(key);
+ if (devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxPackageNameLength(packageName);
+ }
mPackageName = Objects.requireNonNull((packageName));
}
diff --git a/core/java/android/app/admin/PolicySizeVerifier.java b/core/java/android/app/admin/PolicySizeVerifier.java
new file mode 100644
index 000000000000..d5e8ea4525f3
--- /dev/null
+++ b/core/java/android/app/admin/PolicySizeVerifier.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+import android.content.ComponentName;
+import android.os.Parcelable;
+import android.os.PersistableBundle;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.reflect.Field;
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+/**
+ * Utility class containing methods to verify the max allowed size of certain policy types.
+ *
+ * @hide
+ */
+public class PolicySizeVerifier {
+
+ // Binary XML serializer doesn't support longer strings
+ public static final int MAX_POLICY_STRING_LENGTH = 65535;
+ // FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE, Android packages are used in dir names.
+ public static final int MAX_PACKAGE_NAME_LENGTH = 223;
+
+ public static final int MAX_PROFILE_NAME_LENGTH = 200;
+ public static final int MAX_LONG_SUPPORT_MESSAGE_LENGTH = 20000;
+ public static final int MAX_SHORT_SUPPORT_MESSAGE_LENGTH = 200;
+ public static final int MAX_ORG_NAME_LENGTH = 200;
+
+ /**
+ * Throw if string argument is too long to be serialized.
+ */
+ public static void enforceMaxStringLength(String str, String argName) {
+ Preconditions.checkArgument(
+ str.length() <= MAX_POLICY_STRING_LENGTH, argName + " loo long");
+ }
+
+ /**
+ * Throw if package name exceeds max size allowed by the system.
+ */
+ public static void enforceMaxPackageNameLength(String pkg) {
+ Preconditions.checkArgument(
+ pkg.length() <= MAX_PACKAGE_NAME_LENGTH, "Package name too long");
+ }
+
+ /**
+ * Throw if persistable bundle contains any string that's too long to be serialized.
+ */
+ public static void enforceMaxStringLength(PersistableBundle bundle, String argName) {
+ // Persistable bundles can have other persistable bundles as values, traverse with a queue.
+ Queue<PersistableBundle> queue = new ArrayDeque<>();
+ queue.add(bundle);
+ while (!queue.isEmpty()) {
+ PersistableBundle current = queue.remove();
+ for (String key : current.keySet()) {
+ enforceMaxStringLength(key, "key in " + argName);
+ Object value = current.get(key);
+ if (value instanceof String) {
+ enforceMaxStringLength((String) value, "string value in " + argName);
+ } else if (value instanceof String[]) {
+ for (String str : (String[]) value) {
+ enforceMaxStringLength(str, "string value in " + argName);
+ }
+ } else if (value instanceof PersistableBundle) {
+ queue.add((PersistableBundle) value);
+ }
+ }
+ }
+ }
+
+ /**
+ * Throw if Parcelable contains any string that's too long to be serialized.
+ */
+ public static void enforceMaxParcelableFieldsLength(Parcelable parcelable) {
+ Class<?> clazz = parcelable.getClass();
+
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field field : fields) {
+ field.setAccessible(true);
+ try {
+ Object value = field.get(parcelable);
+ if (value instanceof String) {
+ String stringValue = (String) value;
+ enforceMaxStringLength(stringValue, field.getName());
+ }
+
+ if (value instanceof Parcelable) {
+ enforceMaxParcelableFieldsLength((Parcelable) value);
+ }
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Throw if ComponentName contains any string that's too long to be serialized.
+ */
+ public static void enforceMaxComponentNameLength(ComponentName componentName) {
+ enforceMaxPackageNameLength(componentName.getPackageName());
+ enforceMaxStringLength(componentName.flattenToString(), "componentName");
+ }
+
+ /**
+ * Truncates char sequence to maximum length, nulls are ignored.
+ */
+ public static CharSequence truncateIfLonger(CharSequence input, int maxLength) {
+ return input == null || input.length() <= maxLength
+ ? input
+ : input.subSequence(0, maxLength);
+ }
+}
diff --git a/core/java/android/app/admin/StringPolicyValue.java b/core/java/android/app/admin/StringPolicyValue.java
index 14b6dab2899e..f4d4adcfcedb 100644
--- a/core/java/android/app/admin/StringPolicyValue.java
+++ b/core/java/android/app/admin/StringPolicyValue.java
@@ -16,6 +16,8 @@
package android.app.admin;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -29,6 +31,9 @@ public final class StringPolicyValue extends PolicyValue<String> {
public StringPolicyValue(@NonNull String value) {
super(value);
+ if (devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxStringLength(value, "policyValue");
+ }
}
private StringPolicyValue(Parcel source) {
diff --git a/core/java/android/app/admin/StringSetPolicyValue.java b/core/java/android/app/admin/StringSetPolicyValue.java
index cbfc60464467..82fe761a414f 100644
--- a/core/java/android/app/admin/StringSetPolicyValue.java
+++ b/core/java/android/app/admin/StringSetPolicyValue.java
@@ -16,6 +16,8 @@
package android.app.admin;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -31,6 +33,11 @@ public final class StringSetPolicyValue extends PolicyValue<Set<String>> {
public StringSetPolicyValue(@NonNull Set<String> value) {
super(value);
+ if (devicePolicySizeTrackingEnabled()) {
+ for (String str : value) {
+ PolicySizeVerifier.enforceMaxStringLength(str, "policyValue");
+ }
+ }
}
public StringSetPolicyValue(Parcel source) {
diff --git a/core/java/android/app/admin/UserRestrictionPolicyKey.java b/core/java/android/app/admin/UserRestrictionPolicyKey.java
index aeb238041605..d69a5f08ce2e 100644
--- a/core/java/android/app/admin/UserRestrictionPolicyKey.java
+++ b/core/java/android/app/admin/UserRestrictionPolicyKey.java
@@ -17,6 +17,7 @@
package android.app.admin;
import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_KEY;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
import android.annotation.NonNull;
import android.annotation.SystemApi;
@@ -44,6 +45,9 @@ public final class UserRestrictionPolicyKey extends PolicyKey {
@TestApi
public UserRestrictionPolicyKey(@NonNull String identifier, @NonNull String restriction) {
super(identifier);
+ if (devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxStringLength(restriction, "restriction");
+ }
mRestriction = Objects.requireNonNull(restriction);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 14dc0ebb8ad8..105dc880c9a7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -126,7 +126,6 @@ final class DevicePolicyEngine {
//TODO(b/295504706) : Speak to security team to decide what to set Policy_Size_Limit
private static final int POLICY_SIZE_LIMIT = 99999;
-
private final DeviceAdminServiceController mDeviceAdminServiceController;
DevicePolicyEngine(
@@ -1385,7 +1384,6 @@ final class DevicePolicyEngine {
}
}
-
/**
* Removes all local and global policies set by that admin.
*/
@@ -1546,10 +1544,17 @@ final class DevicePolicyEngine {
return false;
}
+ @NonNull
+ private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) {
+ synchronized (mLock) {
+ return mEnforcingAdmins.contains(userId)
+ ? mEnforcingAdmins.get(userId) : Collections.emptySet();
+ }
+ }
+
/**
* Calculate the size of a policy in bytes
*/
-
private static <V> int sizeOf(PolicyValue<V> value) {
try {
Parcel parcel = Parcel.obtain();
@@ -1576,23 +1581,25 @@ final class DevicePolicyEngine {
*
* If the policy size limit is reached then send policy result to admin and return false.
*/
-
private <V> boolean handleAdminPolicySizeLimit(PolicyState<V> policyState, EnforcingAdmin admin,
- PolicyValue<V> value, PolicyDefinition policyDefinition, int userId) {
- int currentSize = 0;
+ PolicyValue<V> value, PolicyDefinition<V> policyDefinition, int userId) {
+ int currentAdminPoliciesSize = 0;
+ int existingPolicySize = 0;
if (mAdminPolicySize.contains(admin.getUserId())
&& mAdminPolicySize.get(
admin.getUserId()).containsKey(admin)) {
- currentSize = mAdminPolicySize.get(admin.getUserId()).get(admin);
+ currentAdminPoliciesSize = mAdminPolicySize.get(admin.getUserId()).get(admin);
}
if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
- currentSize -= sizeOf(policyState.getPoliciesSetByAdmins().get(admin));
+ existingPolicySize = sizeOf(policyState.getPoliciesSetByAdmins().get(admin));
}
int policySize = sizeOf(value);
- if (currentSize + policySize < POLICY_SIZE_LIMIT) {
- increasePolicySizeForAdmin(admin, policySize);
+ if (currentAdminPoliciesSize + policySize - existingPolicySize < POLICY_SIZE_LIMIT) {
+ increasePolicySizeForAdmin(
+ admin, /* policySizeDiff = */ policySize - existingPolicySize);
return true;
} else {
+ Log.w(TAG, "Admin " + admin + "reached max allowed storage limit.");
sendPolicyResultToAdmin(
admin,
policyDefinition,
@@ -1606,8 +1613,7 @@ final class DevicePolicyEngine {
* Increase the int in mAdminPolicySize representing the size of the sum of all
* active policies for that admin.
*/
-
- private <V> void increasePolicySizeForAdmin(EnforcingAdmin admin, int policySize) {
+ private <V> void increasePolicySizeForAdmin(EnforcingAdmin admin, int policySizeDiff) {
if (!mAdminPolicySize.contains(admin.getUserId())) {
mAdminPolicySize.put(admin.getUserId(), new HashMap<>());
}
@@ -1615,14 +1621,13 @@ final class DevicePolicyEngine {
mAdminPolicySize.get(admin.getUserId()).put(admin, /* size= */ 0);
}
mAdminPolicySize.get(admin.getUserId()).put(admin,
- mAdminPolicySize.get(admin.getUserId()).get(admin) + policySize);
+ mAdminPolicySize.get(admin.getUserId()).get(admin) + policySizeDiff);
}
/**
* Decrease the int in mAdminPolicySize representing the size of the sum of all
* active policies for that admin.
*/
-
private <V> void decreasePolicySizeForAdmin(PolicyState<V> policyState, EnforcingAdmin admin) {
if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
mAdminPolicySize.get(admin.getUserId()).put(admin,
@@ -1637,14 +1642,6 @@ final class DevicePolicyEngine {
}
}
- @NonNull
- private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) {
- synchronized (mLock) {
- return mEnforcingAdmins.contains(userId)
- ? mEnforcingAdmins.get(userId) : Collections.emptySet();
- }
- }
-
public void dump(IndentingPrintWriter pw) {
synchronized (mLock) {
pw.println("Local Policies: ");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index fad68ab4cea4..51eee64d12f2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -220,6 +220,10 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_
import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_TELEPHONY_PAUSED_BODY;
import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_TELEPHONY_PAUSED_TITLE;
import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_TELEPHONY_PAUSED_TURN_ON_BUTTON;
+import static android.app.admin.PolicySizeVerifier.MAX_LONG_SUPPORT_MESSAGE_LENGTH;
+import static android.app.admin.PolicySizeVerifier.MAX_ORG_NAME_LENGTH;
+import static android.app.admin.PolicySizeVerifier.MAX_PROFILE_NAME_LENGTH;
+import static android.app.admin.PolicySizeVerifier.MAX_SHORT_SUPPORT_MESSAGE_LENGTH;
import static android.app.admin.ProvisioningException.ERROR_ADMIN_PACKAGE_INSTALLATION_FAILED;
import static android.app.admin.ProvisioningException.ERROR_PRE_CONDITION_FAILED;
import static android.app.admin.ProvisioningException.ERROR_PROFILE_CREATION_FAILED;
@@ -228,6 +232,7 @@ import static android.app.admin.ProvisioningException.ERROR_SETTING_PROFILE_OWNE
import static android.app.admin.ProvisioningException.ERROR_SET_DEVICE_OWNER_FAILED;
import static android.app.admin.ProvisioningException.ERROR_STARTING_PROFILE_FAILED;
import static android.app.admin.flags.Flags.backupServiceSecurityLogEventEnabled;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
import static android.app.admin.flags.Flags.dumpsysPolicyEngineMigrationEnabled;
import static android.app.admin.flags.Flags.headlessDeviceOwnerSingleUserEnabled;
import static android.app.admin.flags.Flags.policyEngineMigrationV2Enabled;
@@ -332,6 +337,7 @@ import android.app.admin.ParcelableResource;
import android.app.admin.PasswordMetrics;
import android.app.admin.PasswordPolicy;
import android.app.admin.PolicyKey;
+import android.app.admin.PolicySizeVerifier;
import android.app.admin.PolicyValue;
import android.app.admin.PreferentialNetworkServiceConfig;
import android.app.admin.SecurityLog;
@@ -537,7 +543,6 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.time.LocalDate;
-import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -550,7 +555,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -588,16 +592,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final int REQUEST_PROFILE_OFF_DEADLINE = 5572;
- // Binary XML serializer doesn't support longer strings
- private static final int MAX_POLICY_STRING_LENGTH = 65535;
- // FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE, Android packages are used in dir names.
- private static final int MAX_PACKAGE_NAME_LENGTH = 223;
-
- private static final int MAX_PROFILE_NAME_LENGTH = 200;
- private static final int MAX_LONG_SUPPORT_MESSAGE_LENGTH = 20000;
- private static final int MAX_SHORT_SUPPORT_MESSAGE_LENGTH = 200;
- private static final int MAX_ORG_NAME_LENGTH = 200;
-
private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1);
private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms
@@ -11537,11 +11531,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Objects.requireNonNull(agent, "agent is null");
- enforceMaxPackageNameLength(agent.getPackageName());
+ PolicySizeVerifier.enforceMaxPackageNameLength(agent.getPackageName());
final String agentAsString = agent.flattenToString();
- enforceMaxStringLength(agentAsString, "agent name");
+ PolicySizeVerifier.enforceMaxStringLength(agentAsString, "agent name");
if (args != null) {
- enforceMaxStringLength(args, "args");
+ PolicySizeVerifier.enforceMaxStringLength(args, "args");
}
int userHandle = mInjector.userHandleGetCallingUserId();
@@ -11833,7 +11827,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (packageList != null) {
for (String pkg : packageList) {
- enforceMaxPackageNameLength(pkg);
+ PolicySizeVerifier.enforceMaxPackageNameLength(pkg);
}
int userId = caller.getUserId();
@@ -12005,7 +11999,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (packageList != null) {
for (String pkg : packageList) {
- enforceMaxPackageNameLength(pkg);
+ PolicySizeVerifier.enforceMaxPackageNameLength(pkg);
}
List<InputMethodInfo> enabledImes = mInjector.binderWithCleanCallingIdentity(() ->
@@ -13710,7 +13704,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return;
}
- enforceMaxStringLength(accountType, "account type");
+ if (!devicePolicySizeTrackingEnabled()) {
+ PolicySizeVerifier.enforceMaxStringLength(accountType, "account type");
+ }
CallerIdentity caller = getCallerIdentity(who, callerPackageName);
synchronized (getLockObject()) {
@@ -14323,7 +14319,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throws SecurityException {
Objects.requireNonNull(packages, "packages is null");
for (String pkg : packages) {
- enforceMaxPackageNameLength(pkg);
+ PolicySizeVerifier.enforceMaxPackageNameLength(pkg);
}
CallerIdentity caller = getCallerIdentity(who, callerPackageName);
@@ -16932,7 +16928,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
CallerIdentity caller;
ActiveAdmin admin;
- message = truncateIfLonger(message, MAX_SHORT_SUPPORT_MESSAGE_LENGTH);
+ message = PolicySizeVerifier.truncateIfLonger(message, MAX_SHORT_SUPPORT_MESSAGE_LENGTH);
if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
@@ -16995,7 +16991,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return;
}
- message = truncateIfLonger(message, MAX_LONG_SUPPORT_MESSAGE_LENGTH);
+ message = PolicySizeVerifier.truncateIfLonger(message, MAX_LONG_SUPPORT_MESSAGE_LENGTH);
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
@@ -17161,7 +17157,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
}
- text = truncateIfLonger(text, MAX_ORG_NAME_LENGTH);
+ text = PolicySizeVerifier.truncateIfLonger(text, MAX_ORG_NAME_LENGTH);
synchronized (getLockObject()) {
if (!isPermissionCheckFlagEnabled()) {
@@ -17447,7 +17443,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
for (String id : ids) {
Preconditions.checkArgument(!TextUtils.isEmpty(id), "ids must not have empty string");
- enforceMaxStringLength(id, "affiliation id");
+ PolicySizeVerifier.enforceMaxStringLength(id, "affiliation id");
}
final Set<String> affiliationIds = new ArraySet<>(ids);
@@ -18994,7 +18990,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkArgument(!admin.getPackageName().equals(target.getPackageName()),
"Provided administrator and target have the same package name.");
if (bundle != null) {
- enforceMaxStringLength(bundle, "bundle");
+ PolicySizeVerifier.enforceMaxStringLength(bundle, "bundle");
}
final CallerIdentity caller = getCallerIdentity(admin);
@@ -23875,53 +23871,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
});
}
- /**
- * Truncates char sequence to maximum length, nulls are ignored.
- */
- private static CharSequence truncateIfLonger(CharSequence input, int maxLength) {
- return input == null || input.length() <= maxLength
- ? input
- : input.subSequence(0, maxLength);
- }
-
- /**
- * Throw if string argument is too long to be serialized.
- */
- private static void enforceMaxStringLength(String str, String argName) {
- Preconditions.checkArgument(
- str.length() <= MAX_POLICY_STRING_LENGTH, argName + " loo long");
- }
-
- private static void enforceMaxPackageNameLength(String pkg) {
- Preconditions.checkArgument(
- pkg.length() <= MAX_PACKAGE_NAME_LENGTH, "Package name too long");
- }
-
- /**
- * Throw if persistable bundle contains any string that we can't serialize.
- */
- private static void enforceMaxStringLength(PersistableBundle bundle, String argName) {
- // Persistable bundles can have other persistable bundles as values, traverse with a queue.
- Queue<PersistableBundle> queue = new ArrayDeque<>();
- queue.add(bundle);
- while (!queue.isEmpty()) {
- PersistableBundle current = queue.remove();
- for (String key : current.keySet()) {
- enforceMaxStringLength(key, "key in " + argName);
- Object value = current.get(key);
- if (value instanceof String) {
- enforceMaxStringLength((String) value, "string value in " + argName);
- } else if (value instanceof String[]) {
- for (String str : (String[]) value) {
- enforceMaxStringLength(str, "string value in " + argName);
- }
- } else if (value instanceof PersistableBundle) {
- queue.add((PersistableBundle) value);
- }
- }
- }
- }
-
private ActiveAdmin getActiveAdminForCaller(@Nullable ComponentName who,
CallerIdentity caller) {
synchronized (getLockObject()) {