From 0033c65aa995484ea6aeaa983c1a227fd14b30a5 Mon Sep 17 00:00:00 2001 From: Jackal Guo Date: Wed, 22 Dec 2021 09:46:15 +0800 Subject: [PATCH] Add enforcement for duplicate permissions Declaring duplicate permissions with different protection levels is not allowed. Add the scheme enforcement for manifest during parsing. Bug: 211934395 Test: atest AppSecurityTests Change-Id: Ieb006ab4abf19baf949e9b5bfd3e3fea16237527 --- .../pm/parsing/ParsingPackageUtils.java | 8 ++++++ .../component/ParsedPermissionUtils.java | 27 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index 16deaa05afcea..f336672ffefae 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED; @@ -934,6 +935,13 @@ public class ParsingPackageUtils { ); } + if (ParsedPermissionUtils.declareDuplicatePermission(pkg)) { + return input.error( + INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Declare duplicate permissions with different protection levels." + ); + } + convertCompatPermissions(pkg); convertSplitPermissions(pkg); diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java index 66e9d3ddca1f1..86c8f02f9fd94 100644 --- a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java @@ -27,6 +27,7 @@ import android.content.pm.parsing.result.ParseResult; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.util.ArrayMap; import android.util.Slog; import com.android.internal.R; @@ -34,6 +35,7 @@ import com.android.internal.R; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.List; /** @hide */ public class ParsedPermissionUtils { @@ -271,4 +273,29 @@ public class ParsedPermissionUtils { } return size; } + + /** + * @return {@code true} if the package declares duplicate permissions with different + * protection levels. + */ + public static boolean declareDuplicatePermission(@NonNull ParsingPackage pkg) { + final List permissions = pkg.getPermissions(); + final int size = permissions.size(); + if (size > 0) { + final ArrayMap checkDuplicatePerm = new ArrayMap<>(size); + for (int i = 0; i < size; i++) { + final ParsedPermission parsedPermission = permissions.get(i); + final String name = parsedPermission.getName(); + final ParsedPermission perm = checkDuplicatePerm.get(name); + // 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 (perm != null && !(perm.isTree() || parsedPermission.isTree()) + && perm.getProtectionLevel() != parsedPermission.getProtectionLevel()) { + return true; + } + checkDuplicatePerm.put(name, parsedPermission); + } + } + return false; + } }