Loading core/java/android/content/pm/PackageParser.java +4 −27 Original line number Diff line number Diff line Loading @@ -131,12 +131,6 @@ public class PackageParser { /** File name in an APK for the Android manifest. */ private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml"; /** * File name in an APK for bytecode. There may be additional bytecode files * but this one is always required for an APK that has code. */ private static final String BYTECODE_FILENAME = "classes.dex"; /** Path prefix for apps on expanded storage */ private static final String MNT_EXPAND = "/mnt/expand/"; Loading Loading @@ -1137,13 +1131,11 @@ public class PackageParser { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); try { collectCertificates( pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags); collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags); if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { for (int i = 0; i < pkg.splitCodePaths.length; i++) { collectCertificates( pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i], parseFlags); collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags); } } } finally { Loading @@ -1151,10 +1143,8 @@ public class PackageParser { } } private static void collectCertificates(Package pkg, File apkFile, int apkFlags, int parseFlags) private static void collectCertificates(Package pkg, File apkFile, int parseFlags) throws PackageParserException { final boolean hasCode = (apkFlags & ApplicationInfo.FLAG_HAS_CODE) != 0; final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0) && hasCode; final String apkPath = apkFile.getAbsolutePath(); // Try to verify the APK using APK Signature Scheme v2. Loading Loading @@ -1202,7 +1192,6 @@ public class PackageParser { } } boolean codeFound = false; StrictJarFile jarFile = null; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor"); Loading @@ -1226,10 +1215,6 @@ public class PackageParser { // Optimization: early termination when APK already verified if (verified) { if ((requireCode) && (jarFile.findEntry(BYTECODE_FILENAME) == null)) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Package " + apkPath + " code is missing"); } return; } Loading @@ -1249,19 +1234,11 @@ public class PackageParser { final String entryName = entry.getName(); if (entryName.startsWith("META-INF/")) continue; if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue; if (entryName.equals(BYTECODE_FILENAME)) { codeFound = true; } toVerify.add(entry); } } if (!codeFound && requireCode) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Package " + apkPath + " code is missing"); } // Verify that entries are signed consistently with the first entry // we encountered. Note that for splits, certificates may have // already been populated during an earlier parse of a base APK. Loading Loading @@ -1349,7 +1326,7 @@ public class PackageParser { final Package tempPkg = new Package(null); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); try { collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/); collectCertificates(tempPkg, apkFile, 0 /*parseFlags*/); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } Loading services/core/java/com/android/server/pm/PackageManagerService.java +51 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,7 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.Xml; import android.util.jar.StrictJarFile; import android.view.Display; import com.android.internal.R; Loading Loading @@ -7643,6 +7644,52 @@ public class PackageManagerService extends IPackageManager.Stub { } } /** * Returns {@code true} if the given file contains code. Otherwise {@code false}. */ private static boolean apkHasCode(String fileName) { StrictJarFile jarFile = null; try { jarFile = new StrictJarFile(fileName, false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/); return jarFile.findEntry("classes.dex") != null; } catch (IOException ignore) { } finally { try { jarFile.close(); } catch (IOException ignore) {} } return false; } /** * Enforces code policy for the package. This ensures that if an APK has * declared hasCode="true" in its manifest that the APK actually contains * code. * * @throws PackageManagerException If bytecode could not be found when it should exist */ private static void enforceCodePolicy(PackageParser.Package pkg) throws PackageManagerException { final boolean shouldHaveCode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0; if (shouldHaveCode && !apkHasCode(pkg.baseCodePath)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Package " + pkg.baseCodePath + " code is missing"); } if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { for (int i = 0; i < pkg.splitCodePaths.length; i++) { final boolean splitShouldHaveCode = (pkg.splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0; if (splitShouldHaveCode && !apkHasCode(pkg.splitCodePaths[i])) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Package " + pkg.splitCodePaths[i] + " code is missing"); } } } } private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, final int policyFlags, final int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { Loading Loading @@ -7687,6 +7734,10 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; } if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) { enforceCodePolicy(pkg); } if (mCustomResolverComponentName != null && mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) { setUpCustomResolverActivity(pkg); Loading Loading
core/java/android/content/pm/PackageParser.java +4 −27 Original line number Diff line number Diff line Loading @@ -131,12 +131,6 @@ public class PackageParser { /** File name in an APK for the Android manifest. */ private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml"; /** * File name in an APK for bytecode. There may be additional bytecode files * but this one is always required for an APK that has code. */ private static final String BYTECODE_FILENAME = "classes.dex"; /** Path prefix for apps on expanded storage */ private static final String MNT_EXPAND = "/mnt/expand/"; Loading Loading @@ -1137,13 +1131,11 @@ public class PackageParser { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); try { collectCertificates( pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags); collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags); if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { for (int i = 0; i < pkg.splitCodePaths.length; i++) { collectCertificates( pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i], parseFlags); collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags); } } } finally { Loading @@ -1151,10 +1143,8 @@ public class PackageParser { } } private static void collectCertificates(Package pkg, File apkFile, int apkFlags, int parseFlags) private static void collectCertificates(Package pkg, File apkFile, int parseFlags) throws PackageParserException { final boolean hasCode = (apkFlags & ApplicationInfo.FLAG_HAS_CODE) != 0; final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0) && hasCode; final String apkPath = apkFile.getAbsolutePath(); // Try to verify the APK using APK Signature Scheme v2. Loading Loading @@ -1202,7 +1192,6 @@ public class PackageParser { } } boolean codeFound = false; StrictJarFile jarFile = null; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor"); Loading @@ -1226,10 +1215,6 @@ public class PackageParser { // Optimization: early termination when APK already verified if (verified) { if ((requireCode) && (jarFile.findEntry(BYTECODE_FILENAME) == null)) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Package " + apkPath + " code is missing"); } return; } Loading @@ -1249,19 +1234,11 @@ public class PackageParser { final String entryName = entry.getName(); if (entryName.startsWith("META-INF/")) continue; if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue; if (entryName.equals(BYTECODE_FILENAME)) { codeFound = true; } toVerify.add(entry); } } if (!codeFound && requireCode) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Package " + apkPath + " code is missing"); } // Verify that entries are signed consistently with the first entry // we encountered. Note that for splits, certificates may have // already been populated during an earlier parse of a base APK. Loading Loading @@ -1349,7 +1326,7 @@ public class PackageParser { final Package tempPkg = new Package(null); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); try { collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/); collectCertificates(tempPkg, apkFile, 0 /*parseFlags*/); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } Loading
services/core/java/com/android/server/pm/PackageManagerService.java +51 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,7 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.Xml; import android.util.jar.StrictJarFile; import android.view.Display; import com.android.internal.R; Loading Loading @@ -7643,6 +7644,52 @@ public class PackageManagerService extends IPackageManager.Stub { } } /** * Returns {@code true} if the given file contains code. Otherwise {@code false}. */ private static boolean apkHasCode(String fileName) { StrictJarFile jarFile = null; try { jarFile = new StrictJarFile(fileName, false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/); return jarFile.findEntry("classes.dex") != null; } catch (IOException ignore) { } finally { try { jarFile.close(); } catch (IOException ignore) {} } return false; } /** * Enforces code policy for the package. This ensures that if an APK has * declared hasCode="true" in its manifest that the APK actually contains * code. * * @throws PackageManagerException If bytecode could not be found when it should exist */ private static void enforceCodePolicy(PackageParser.Package pkg) throws PackageManagerException { final boolean shouldHaveCode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0; if (shouldHaveCode && !apkHasCode(pkg.baseCodePath)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Package " + pkg.baseCodePath + " code is missing"); } if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { for (int i = 0; i < pkg.splitCodePaths.length; i++) { final boolean splitShouldHaveCode = (pkg.splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0; if (splitShouldHaveCode && !apkHasCode(pkg.splitCodePaths[i])) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Package " + pkg.splitCodePaths[i] + " code is missing"); } } } } private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, final int policyFlags, final int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { Loading Loading @@ -7687,6 +7734,10 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; } if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) { enforceCodePolicy(pkg); } if (mCustomResolverComponentName != null && mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) { setUpCustomResolverActivity(pkg); Loading