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

Commit 4402aca9 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Force verifying updated priv apps on boot if enabled"

parents 00aa5879 0c8f2e01
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -8183,12 +8183,12 @@ public class PackageManagerService extends IPackageManager.Stub
    }
    private void collectCertificatesLI(PackageSetting ps, PackageParser.Package pkg,
            final @ParseFlags int parseFlags) throws PackageManagerException {
            final @ParseFlags int parseFlags, boolean forceCollect) throws PackageManagerException {
        // When upgrading from pre-N MR1, verify the package time stamp using the package
        // directory and not the APK file.
        final long lastModifiedTime = mIsPreNMR1Upgrade
                ? new File(pkg.codePath).lastModified() : getLastModifiedTime(pkg);
        if (ps != null
        if (ps != null && !forceCollect
                && ps.codePathString.equals(pkg.codePath)
                && ps.timeStamp == lastModifiedTime
                && !isCompatSignatureUpdateNeeded(pkg)
@@ -8211,7 +8211,8 @@ public class PackageManagerService extends IPackageManager.Stub
            Slog.w(TAG, "PackageSetting for " + ps.name
                    + " is missing signatures.  Collecting certs again to recover them.");
        } else {
            Slog.i(TAG, toString() + " changed; collecting certs");
            Slog.i(TAG, pkg.codePath + " changed; collecting certs" +
                    (forceCollect ? " (forced)" : ""));
        }
        try {
@@ -8452,8 +8453,11 @@ public class PackageManagerService extends IPackageManager.Stub
                    + " better than this " + pkg.getLongVersionCode());
        }
        // verify certificates against what was last scanned
        collectCertificatesLI(pkgSetting, pkg, parseFlags);
        // Verify certificates against what was last scanned. If it is an updated priv app, we will
        // force the verification. Full apk verification will happen unless apk verity is set up for
        // the file. In that case, only small part of the apk is verified upfront.
        collectCertificatesLI(pkgSetting, pkg, parseFlags,
                PackageManagerServiceUtils.isApkVerificationForced(disabledPkgSetting));
        boolean shouldHideSystemApp = false;
        // A new application appeared on /system, but, we already have a copy of
@@ -9723,6 +9727,7 @@ public class PackageManagerService extends IPackageManager.Stub
        final @ScanFlags int scanFlags = request.scanFlags;
        final PackageSetting oldPkgSetting = request.oldPkgSetting;
        final PackageSetting originalPkgSetting = request.originalPkgSetting;
        final PackageSetting disabledPkgSetting = request.disabledPkgSetting;
        final UserHandle user = request.user;
        final String realPkgName = request.realPkgName;
        final PackageSetting pkgSetting = result.pkgSetting;
@@ -9805,7 +9810,7 @@ public class PackageManagerService extends IPackageManager.Stub
            try {
                final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg);
                final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg);
                final boolean compatMatch = verifySignatures(signatureCheckPs,
                final boolean compatMatch = verifySignatures(signatureCheckPs, disabledPkgSetting,
                        pkg.mSigningDetails, compareCompat, compareRecover);
                // The new KeySets will be re-added later in the scanning process.
                if (compatMatch) {
@@ -16575,8 +16580,9 @@ public class PackageManagerService extends IPackageManager.Stub
                    try {
                        final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg);
                        final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg);
                        // We don't care about disabledPkgSetting on install for now.
                        final boolean compatMatch = verifySignatures(
                                signatureCheckPs, pkg.mSigningDetails, compareCompat,
                                signatureCheckPs, null, pkg.mSigningDetails, compareCompat,
                                compareRecover);
                        // The new KeySets will be re-added later in the scanning process.
                        if (compatMatch) {
+43 −2
Original line number Diff line number Diff line
@@ -33,10 +33,12 @@ import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.PackageDexUsage;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.os.Build;
@@ -45,6 +47,7 @@ import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.service.pm.PackageServiceDumpProto;
import android.system.ErrnoException;
@@ -546,14 +549,47 @@ public class PackageManagerServiceUtils {
        return false;
    }

    /**
     * Make sure the updated priv app is signed with the same key as the original APK file on the
     * /system partition.
     *
     * <p>The rationale is that {@code disabledPkg} is a PackageSetting backed by xml files in /data
     * and is not tamperproof.
     */
    private static boolean matchSignatureInSystem(PackageSetting pkgSetting,
            PackageSetting disabledPkgSetting) {
        try {
            PackageParser.collectCertificates(disabledPkgSetting.pkg,
                    PackageParser.PARSE_IS_SYSTEM_DIR);
            if (compareSignatures(pkgSetting.signatures.mSignatures,
                        disabledPkgSetting.signatures.mSignatures)
                    != PackageManager.SIGNATURE_MATCH) {
                logCriticalInfo(Log.ERROR, "Updated system app mismatches cert on /system: " +
                        pkgSetting.name);
                return false;
            }
        } catch (PackageParserException e) {
            logCriticalInfo(Log.ERROR, "Failed to collect cert for " + pkgSetting.name + ": " +
                    e.getMessage());
            return false;
        }
        return true;
    }

    /** Returns true to force apk verification if the updated package (in /data) is a priv app. */
    static boolean isApkVerificationForced(@Nullable PackageSetting disabledPs) {
        return disabledPs != null && disabledPs.isPrivileged() &&
                SystemProperties.getInt("ro.apk_verity.mode", 0) != 0;
    }

    /**
     * Verifies that signatures match.
     * @returns {@code true} if the compat signatures were matched; otherwise, {@code false}.
     * @throws PackageManagerException if the signatures did not match.
     */
    public static boolean verifySignatures(PackageSetting pkgSetting,
            PackageParser.SigningDetails parsedSignatures, boolean compareCompat,
            boolean compareRecover)
            PackageSetting disabledPkgSetting, PackageParser.SigningDetails parsedSignatures,
            boolean compareCompat, boolean compareRecover)
            throws PackageManagerException {
        final String packageName = pkgSetting.name;
        boolean compatMatch = false;
@@ -572,6 +608,11 @@ public class PackageManagerServiceUtils {
                        packageName, pkgSetting.signatures.mSignatures,
                        parsedSignatures.signatures);
            }

            if (!match && isApkVerificationForced(disabledPkgSetting)) {
                match = matchSignatureInSystem(pkgSetting, disabledPkgSetting);
            }

            if (!match) {
                throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                        "Package " + packageName +