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

Commit ded40816 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "signature-permission-allowlist-test" into main

* changes:
  Add system server test API to force enforce signature permission allowlist.
  Add system server test API to override package signing details.
parents 09d78e79 70baff8c
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();
        }
    }

    /**
+3 −0
Original line number Diff line number Diff line
# Bug component: 137825

include platform/frameworks/base:/core/java/android/permission/OWNERS
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.permission;

import android.annotation.TestApi;
import com.android.internal.annotations.Keep;

/**
 * In-process API for server side permission related infrastructure.
 *
 * @hide
 */
@Keep
@TestApi
public interface PermissionManagerLocal {

    /**
     * Get whether signature permission allowlist is enforced even on debuggable builds.
     *
     * @return whether the signature permission allowlist is force enforced
     */
    @TestApi
    boolean isSignaturePermissionAllowlistForceEnforced();

    /**
     * Set whether signature permission allowlist is enforced even on debuggable builds.
     *
     * @param forceEnforced whether the signature permission allowlist is force enforced
     */
    @TestApi
    void setSignaturePermissionAllowlistForceEnforced(boolean forceEnforced);
}
+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;
Loading