From 7cb3a32293ef72498a1b44b11a64341c11d941b8 Mon Sep 17 00:00:00 2001 From: Michael Groover Date: Fri, 25 Mar 2022 17:25:03 -0700 Subject: [PATCH] Restore V2+ signature requirement for system apps In Android R, the platform began enforcing a requirement that apps targeting this release or later must be signed with at least the V2 signature scheme. Initially, this requirement was applied to system apps, but due to the build system stripping V2+ signatures due to compressed dex and library files, the requirement had to be relaxed for system apps; since then, the system apps have been updated with uncompressed dex and library files to prevent the signature stripping by the build system. This commit restores the requirement that system apps targeting SDK version 30+ must be signed with at least the V2 signature scheme. Bug: 215046612 Test: Manually verified fix properly identified system app without V2+ signature Change-Id: I5b482931a99ea8c2308d516912317ff0828153e2 --- .../java/android/content/pm/PackageParser.java | 6 ++---- .../server/pm/InstallPackageHelper.java | 4 ++-- .../android/server/pm/ScanPackageUtils.java | 18 ++++++++---------- .../pm/pkg/parsing/ParsingPackageUtils.java | 6 ++---- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 4d4a57db84bea..44dc28d2b0faf 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1414,11 +1414,9 @@ public class PackageParser { final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); final ParseResult result; if (skipVerify) { - // systemDir APKs are already trusted, save time by not verifying; since the signature - // is not verified and some system apps can have their V2+ signatures stripped allow - // pulling the certs from the jar signature. + // systemDir APKs are already trusted, save time by not verifying result = ApkSignatureVerifier.unsafeGetCertsWithoutVerification( - input, apkPath, SigningDetails.SignatureSchemeVersion.JAR); + input, apkPath, minSignatureScheme); } else { result = ApkSignatureVerifier.verify(input, apkPath, minSignatureScheme); } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 6e4d19f8d277d..d99a303ca3274 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -4190,8 +4190,8 @@ final class InstallPackageHelper { assertOverlayIsValid(pkg, parseFlags, scanFlags); } - // If the package is not on a system partition ensure it is signed with at least the - // minimum signature scheme version required for its target SDK. + // Ensure the package is signed with at least the minimum signature scheme version + // required for its target SDK. ScanPackageUtils.assertMinSignatureSchemeIsValid(pkg, parseFlags); } } diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java index 4e8313bf1891d..0dc188b75d5e9 100644 --- a/services/core/java/com/android/server/pm/ScanPackageUtils.java +++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java @@ -690,16 +690,14 @@ final class ScanPackageUtils { public static void assertMinSignatureSchemeIsValid(AndroidPackage pkg, @ParsingPackageUtils.ParseFlags int parseFlags) throws PackageManagerException { - if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) { - int minSignatureSchemeVersion = - ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk( - pkg.getTargetSdkVersion()); - if (pkg.getSigningDetails().getSignatureSchemeVersion() - < minSignatureSchemeVersion) { - throw new PackageManagerException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, - "No signature found in package of version " + minSignatureSchemeVersion - + " or newer for package " + pkg.getPackageName()); - } + int minSignatureSchemeVersion = + ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk( + pkg.getTargetSdkVersion()); + if (pkg.getSigningDetails().getSignatureSchemeVersion() + < minSignatureSchemeVersion) { + throw new PackageManagerException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, + "No signature found in package of version " + minSignatureSchemeVersion + + " or newer for package " + pkg.getPackageName()); } } diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java index 3eaca9dddcc41..172bf1cce60a5 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java @@ -3069,11 +3069,9 @@ public class ParsingPackageUtils { } final ParseResult verified; if (skipVerify) { - // systemDir APKs are already trusted, save time by not verifying; since the - // signature is not verified and some system apps can have their V2+ signatures - // stripped allow pulling the certs from the jar signature. + // systemDir APKs are already trusted, save time by not verifying verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(input, baseCodePath, - SigningDetails.SignatureSchemeVersion.JAR); + minSignatureScheme); } else { verified = ApkSignatureVerifier.verify(input, baseCodePath, minSignatureScheme); }