Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 069ed700 authored by Todd Kennedy's avatar Todd Kennedy Committed by Android (Google) Code Review
Browse files

Merge "Always perform has code check" into nyc-dev

parents 79c4dca2 f720a9d9
Loading
Loading
Loading
Loading
+4 −27
Original line number Diff line number Diff line
@@ -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/";

@@ -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 {
@@ -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.
@@ -1202,7 +1192,6 @@ public class PackageParser {
            }
        }

        boolean codeFound = false;
        StrictJarFile jarFile = null;
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
@@ -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;
            }

@@ -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.
@@ -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);
                }
+51 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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 {
@@ -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);