summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2023-05-16 00:07:30 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-05-16 00:07:30 +0000
commitf943201e7e3b13b05b016bfa7e0d67471e21293f (patch)
tree7139bf365c5919c86ebfbe52e5d0e3704c5ed4de
parent7161f2a5a8b7bf465f3495848f08c477511eaf2a (diff)
parent426ad6067cdafac0abdb75d820684fd09722d7c3 (diff)
Merge changes from topic "presubmit-am-596ac78c570647d8a0f30d123eb656a7" into sc-qpr1-dev
* changes: [automerge] Ensure policy has no absurdly long strings 2p: 12c201509e Ensure policy has no absurdly long strings
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java3
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java93
2 files changed, 92 insertions, 4 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index aea502828c36..efa08c8cae3b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11283,7 +11283,8 @@ public class DevicePolicyManager {
/**
* Called by a device admin to set the long support message. This will be displayed to the user
- * in the device administators settings screen.
+ * in the device administrators settings screen. If the message is longer than 20000 characters
+ * it may be truncated.
* <p>
* If the long support message needs to be localized, it is the responsibility of the
* {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index acdf2d0ab3ea..903df2d6efee 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -360,6 +360,7 @@ 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;
@@ -371,6 +372,7 @@ 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.TimeUnit;
import java.util.function.Function;
@@ -399,6 +401,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
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_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
@@ -9869,6 +9880,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(admin, "admin is null");
Objects.requireNonNull(agent, "agent is null");
+ enforceMaxPackageNameLength(agent.getPackageName());
+ final String agentAsString = agent.flattenToString();
+ enforceMaxStringLength(agentAsString, "agent name");
+ if (args != null) {
+ enforceMaxStringLength(args, "args");
+ }
final int userHandle = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
@@ -10107,6 +10124,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
if (packageList != null) {
+ for (String pkg : (List<String>) packageList) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
int userId = caller.getUserId();
final List<AccessibilityServiceInfo> enabledServices;
long id = mInjector.binderClearCallingIdentity();
@@ -10273,6 +10294,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
if (packageList != null) {
+ for (String pkg : (List<String>) packageList) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
List<InputMethodInfo> enabledImes = mInjector.binderWithCleanCallingIdentity(() ->
InputMethodManagerInternal.get().getEnabledInputMethodListAsUser(userId));
if (enabledImes != null) {
@@ -11497,6 +11522,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+ enforceMaxStringLength(accountType, "account type");
+
final CallerIdentity caller = getCallerIdentity(who);
synchronized (getLockObject()) {
/*
@@ -11915,6 +11942,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throws SecurityException {
Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(packages, "packages is null");
+ for (String pkg : packages) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
final CallerIdentity caller = getCallerIdentity(who);
synchronized (getLockObject()) {
@@ -13924,6 +13955,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+ message = truncateIfLonger(message, MAX_SHORT_SUPPORT_MESSAGE_LENGTH);
+
final CallerIdentity caller = getCallerIdentity(who);
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who, caller.getUid());
@@ -13956,6 +13989,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return;
}
+
+ message = truncateIfLonger(message, MAX_LONG_SUPPORT_MESSAGE_LENGTH);
+
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
synchronized (getLockObject()) {
@@ -14105,6 +14141,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
+ text = truncateIfLonger(text, MAX_ORG_NAME_LENGTH);
+
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
if (!TextUtils.equals(admin.organizationName, text)) {
@@ -14354,9 +14392,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throw new IllegalArgumentException("ids must not be null");
}
for (String id : ids) {
- if (TextUtils.isEmpty(id)) {
- throw new IllegalArgumentException("ids must not contain empty string");
- }
+ Preconditions.checkArgument(!TextUtils.isEmpty(id), "ids must not have empty string");
+ enforceMaxStringLength(id, "affiliation id");
}
final Set<String> affiliationIds = new ArraySet<>(ids);
@@ -15613,6 +15650,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
"Provided administrator and target are the same object.");
Preconditions.checkArgument(!admin.getPackageName().equals(target.getPackageName()),
"Provided administrator and target have the same package name.");
+ if (bundle != null) {
+ enforceMaxStringLength(bundle, "bundle");
+ }
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
@@ -17697,4 +17737,51 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
&& mInjector.getUsbManager().getUsbHalVersion() >= UsbManager.USB_HAL_V1_3
);
}
+
+ /**
+ * 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);
+ }
+ }
+ }
+ }
}