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

Commit 2239f2ca authored by Hai Zhang's avatar Hai Zhang
Browse files

Add system server test API to override package signing details.

This API is only available to code within system server process and only
on debuggable builds.

Bug: 308573169
Test: TODO
Change-Id: Iaf67a9f1a45e11faf236be5b179137905295b493
parent ebbf77ea
Loading
Loading
Loading
Loading
+58 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.util.apk.ApkSignatureSchemeV4Verifier.APK_SIGNATURE_SCHEME_DEFAULT;

import android.annotation.NonNull;
import android.content.pm.Signature;
import android.content.pm.SigningDetails;
import android.content.pm.SigningDetails.SignatureSchemeVersion;
@@ -33,9 +34,12 @@ import android.content.pm.parsing.result.ParseResult;
import android.os.Build;
import android.os.Trace;
import android.os.incremental.V4Signature;
import android.util.ArrayMap;
import android.util.Pair;
import android.util.Slog;
import android.util.jar.StrictJarFile;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;

import libcore.io.IoUtils;
@@ -63,8 +67,14 @@ import java.util.zip.ZipEntry;
 */
public class ApkSignatureVerifier {

    private static final String LOG_TAG = "ApkSignatureVerifier";

    private static final AtomicReference<byte[]> sBuffer = new AtomicReference<>();

    @GuardedBy("sOverrideSigningDetails")
    private static final ArrayMap<SigningDetails, SigningDetails> sOverrideSigningDetails =
            new ArrayMap<>();

    /**
     * Verifies the provided APK and returns the certificates associated with each signer.
     */
@@ -95,7 +105,54 @@ public class ApkSignatureVerifier {
        if (result.isError()) {
            return input.error(result);
        }
        return input.success(result.getResult().signingDetails);
        SigningDetails signingDetails = result.getResult().signingDetails;
        if (Build.isDebuggable()) {
            SigningDetails overrideSigningDetails;
            synchronized (sOverrideSigningDetails) {
                overrideSigningDetails = sOverrideSigningDetails.get(signingDetails);
            }
            if (overrideSigningDetails != null) {
                Slog.i(LOG_TAG, "Applying override signing details for APK " + apkPath);
                signingDetails = overrideSigningDetails;
            }
        }
        return input.success(signingDetails);
    }

    /**
     * Add a pair of signing details so that packages signed with {@code oldSigningDetails} will
     * behave as if they are signed by the {@code newSigningDetails}.
     *
     * @param oldSigningDetails the original signing detail of the package
     * @param newSigningDetails the new signing detail that will replace the original one
     */
    public static void addOverrideSigningDetails(@NonNull SigningDetails oldSigningDetails,
            @NonNull SigningDetails newSigningDetails) {
        synchronized (sOverrideSigningDetails) {
            sOverrideSigningDetails.put(oldSigningDetails, newSigningDetails);
        }
    }

    /**
     * Remove a pair of signing details previously added via {@link #addOverrideSigningDetails} by
     * the old signing details.
     *
     * @param oldSigningDetails the original signing detail of the package
     * @throws SecurityException if the build is not debuggable
     */
    public static void removeOverrideSigningDetails(@NonNull SigningDetails oldSigningDetails) {
        synchronized (sOverrideSigningDetails) {
            sOverrideSigningDetails.remove(oldSigningDetails);
        }
    }

    /**
     * Clear all pairs of signing details previously added via {@link #addOverrideSigningDetails}.
     */
    public static void clearOverrideSigningDetails() {
        synchronized (sOverrideSigningDetails) {
            sOverrideSigningDetails.clear();
        }
    }

    /**
+44 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.pm.SigningDetails;
import android.os.Binder;
import android.os.UserHandle;

@@ -123,6 +125,48 @@ public interface PackageManagerLocal {
    @NonNull
    FilteredSnapshot withFilteredSnapshot(int callingUid, @NonNull UserHandle user);

    /**
     * Add a pair of signing details so that packages signed with {@code oldSigningDetails} will
     * behave as if they are signed by the {@code newSigningDetails}.
     * <p>
     * This is only available on {@link android.os.Build#isDebuggable debuggable} builds.
     *
     * @param oldSigningDetails the original signing detail of the package
     * @param newSigningDetails the new signing detail that will replace the original one
     * @throws SecurityException if the build is not debuggable
     *
     * @hide
     */
    @TestApi
    void addOverrideSigningDetails(@NonNull SigningDetails oldSigningDetails,
            @NonNull SigningDetails newSigningDetails);

    /**
     * Remove a pair of signing details previously added via {@link #addOverrideSigningDetails} by
     * the old signing details.
     * <p>
     * This is only available on {@link android.os.Build#isDebuggable debuggable} builds.
     *
     * @param oldSigningDetails the original signing detail of the package
     * @throws SecurityException if the build is not debuggable
     *
     * @hide
     */
    @TestApi
    void removeOverrideSigningDetails(@NonNull SigningDetails oldSigningDetails);

    /**
     * Clear all pairs of signing details previously added via {@link #addOverrideSigningDetails}.
     * <p>
     * This is only available on {@link android.os.Build#isDebuggable debuggable} builds.
     *
     * @throws SecurityException if the build is not debuggable
     *
     * @hide
     */
    @TestApi
    void clearOverrideSigningDetails();

    /**
     * @hide
     */
+28 −0
Original line number Diff line number Diff line
@@ -20,9 +20,12 @@ import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.pm.SigningDetails;
import android.os.Binder;
import android.os.Build;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.apk.ApkSignatureVerifier;

import com.android.server.pm.Computer;
import com.android.server.pm.PackageManagerLocal;
@@ -72,6 +75,31 @@ public class PackageManagerLocalImpl implements PackageManagerLocal {
                mService.snapshotComputer(false /*allowLiveComputer*/), null);
    }

    @Override
    public void addOverrideSigningDetails(@NonNull SigningDetails oldSigningDetails,
            @NonNull SigningDetails newSigningDetails) {
        if (!Build.isDebuggable()) {
            throw new SecurityException("This test API is only available on debuggable builds");
        }
        ApkSignatureVerifier.addOverrideSigningDetails(oldSigningDetails, newSigningDetails);
    }

    @Override
    public void removeOverrideSigningDetails(@NonNull SigningDetails oldSigningDetails) {
        if (!Build.isDebuggable()) {
            throw new SecurityException("This test API is only available on debuggable builds");
        }
        ApkSignatureVerifier.removeOverrideSigningDetails(oldSigningDetails);
    }

    @Override
    public void clearOverrideSigningDetails() {
        if (!Build.isDebuggable()) {
            throw new SecurityException("This test API is only available on debuggable builds");
        }
        ApkSignatureVerifier.clearOverrideSigningDetails();
    }

    private abstract static class BaseSnapshotImpl implements AutoCloseable {

        private boolean mClosed;