diff options
| author | 2022-04-28 20:23:58 +0000 | |
|---|---|---|
| committer | 2022-05-16 02:06:24 +0000 | |
| commit | 31bd425bb66b108cdec357a00f4a586379bcd33a (patch) | |
| tree | d817cab636a4f75ff8a613bb470e5d3b49860326 | |
| parent | 248bbf2dca0b94db3666bd0d6326102ff7208ffb (diff) | |
Fix duplicate permission privilege escalation
Duplicate permissions definition with different group allows
privilege permission escalation to a different permission group.
Android studio and gradle plugin does not allow duplicate
permissions with different attributes, these tools only allow
if duplicate permissions are exact copies.
Also platform stores permissions in map at multiple places with
permission name as key. This suggests that we can disallow
duplicate permissions during package install/update.
Bug: 213323615
Test: manual
Change-Id: I6f44e740897305e7a0553c1cf6c3af37faf02a2e
Merged-In: I1910dca44104e35a57eba4acfa8188cd9b8626ac
Merged-In: I34120fff2ec2a158dfa55779d2afd4bbd49487ff
Merged-In: I9bc839836786a0876e67fd73c05f8944bb532249
| -rw-r--r-- | core/java/android/content/pm/PackageParser.java | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index b3776787cc2b..1ea6e11d994d 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -89,6 +89,7 @@ import android.util.AttributeSet; import android.util.Base64; import android.util.ByteStringUtils; import android.util.DisplayMetrics; +import android.util.EventLog; import android.util.Log; import android.util.PackageUtils; import android.util.Pair; @@ -132,6 +133,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @@ -2501,6 +2503,12 @@ public class PackageParser { } } + if (declareDuplicatePermission(pkg)) { + outError[0] = "Found duplicate permission with a different attribute value."; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + if (supportsSmallScreens < 0 || (supportsSmallScreens > 0 && pkg.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.DONUT)) { @@ -2540,6 +2548,51 @@ public class PackageParser { return pkg; } + /** + * @return {@code true} if the package declares malformed duplicate permissions. + */ + public static boolean declareDuplicatePermission(@NonNull Package pkg) { + final List<Permission> permissions = pkg.permissions; + final int size = permissions.size(); + if (size > 0) { + final ArrayMap<String, Permission> checkDuplicatePerm = new ArrayMap<>(size); + for (int i = 0; i < size; i++) { + final Permission permissionDefinition = permissions.get(i); + final String name = permissionDefinition.info.name; + final Permission perm = checkDuplicatePerm.get(name); + if (isMalformedDuplicate(permissionDefinition, perm)) { + // Fix for b/213323615 + EventLog.writeEvent(0x534e4554, "213323615", + "The package " + pkg.packageName + " seems malicious"); + return true; + } + checkDuplicatePerm.put(name, permissionDefinition); + } + } + return false; + } + + /** + * Determines if a duplicate permission is malformed .i.e. defines different protection level + * or group. + */ + private static boolean isMalformedDuplicate(Permission p1, Permission p2) { + // Since a permission tree is also added as a permission with normal protection + // level, we need to skip if the parsedPermission is a permission tree. + if (p1 == null || p2 == null || p1.tree || p2.tree) { + return false; + } + + if (p1.info.getProtection() != p2.info.getProtection()) { + return true; + } + if (!Objects.equals(p1.info.group, p2.info.group)) { + return true; + } + + return false; + } + private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) { if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) { |