Cap the size of app-defined permission trees
Bug 13529742
Change-Id: I46c2ebc39caf4a9eacbffbb35fc386c2a1cedc12
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cb4cf98..a01c586 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -200,6 +200,9 @@
private static final boolean GET_CERTIFICATES = true;
+ // Cap the size of permission trees that 3rd party apps can define
+ private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768; // characters of text
+
private static final int REMOVE_EVENTS =
FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
private static final int ADD_EVENTS =
@@ -2357,7 +2360,35 @@
//if (pi1.descriptionRes != pi2.descriptionRes) return false;
return true;
}
-
+
+ int permissionInfoFootprint(PermissionInfo info) {
+ int size = info.name.length();
+ if (info.nonLocalizedLabel != null) size += info.nonLocalizedLabel.length();
+ if (info.nonLocalizedDescription != null) size += info.nonLocalizedDescription.length();
+ return size;
+ }
+
+ int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
+ int size = 0;
+ for (BasePermission perm : mSettings.mPermissions.values()) {
+ if (perm.uid == tree.uid) {
+ size += perm.name.length() + permissionInfoFootprint(perm.perm.info);
+ }
+ }
+ return size;
+ }
+
+ void enforcePermissionCapLocked(PermissionInfo info, BasePermission tree) {
+ // We calculate the max size of permissions defined by this uid and throw
+ // if that plus the size of 'info' would exceed our stated maximum.
+ if (tree.uid != Process.SYSTEM_UID) {
+ final int curTreeSize = calculateCurrentPermissionFootprintLocked(tree);
+ if (curTreeSize + permissionInfoFootprint(info) > MAX_PERMISSION_TREE_FOOTPRINT) {
+ throw new SecurityException("Permission tree size cap exceeded");
+ }
+ }
+ }
+
boolean addPermissionLocked(PermissionInfo info, boolean async) {
if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
throw new SecurityException("Label must be specified in permission");
@@ -2368,6 +2399,7 @@
boolean changed = true;
int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
if (added) {
+ enforcePermissionCapLocked(info, tree);
bp = new BasePermission(info.name, tree.sourcePackage,
BasePermission.TYPE_DYNAMIC);
} else if (bp.type != BasePermission.TYPE_DYNAMIC) {