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

Commit b67d55ff authored by Song Chun Fan's avatar Song Chun Fan
Browse files

[8/N] per-user global verification policy

+ global verification policy can be different per user
+ log initial verification policy per session for debugging

FLAG: android.content.pm.verification_service

BUG: 360129657
Test: atest CtsPackageManagerTestCases:VerifierServiceTest

Change-Id: I309a4858ad2b0a21a05a5e09d3598dad82f21f7c
parent 9b5439b3
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -95,8 +95,8 @@ interface IPackageInstaller {
    void reportUnarchivalStatus(int unarchiveId, int status, long requiredStorageBytes, in PendingIntent userActionIntent, in UserHandle userHandle);

    @EnforcePermission("VERIFICATION_AGENT")
    int getVerificationPolicy();
    int getVerificationPolicy(int userId);

    @EnforcePermission("VERIFICATION_AGENT")
    boolean setVerificationPolicy(int policy);
    boolean setVerificationPolicy(int policy, int userId);
}
+2 −2
Original line number Diff line number Diff line
@@ -1613,7 +1613,7 @@ public class PackageInstaller {
    @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
    public final @VerificationPolicy int getVerificationPolicy() {
        try {
            return mInstaller.getVerificationPolicy();
            return mInstaller.getVerificationPolicy(mUserId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -1631,7 +1631,7 @@ public class PackageInstaller {
    @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
    public final boolean setVerificationPolicy(@VerificationPolicy int policy) {
        try {
            return mInstaller.setVerificationPolicy(policy);
            return mInstaller.setVerificationPolicy(policy, mUserId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+8 −1
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ public final class PackageInstallerHistoricalSession {
    private final String mSessionErrorMessage;
    private final String mPreVerifiedDomains;
    private final String mPackageName;
    private final int mInitialVerificationPolicy;
    private final int mCurrentVerificationPolicy;

    PackageInstallerHistoricalSession(int sessionId, int userId, int originalInstallerUid,
            String originalInstallerPackageName, InstallSource installSource, int installerUid,
@@ -90,7 +92,8 @@ public final class PackageInstallerHistoricalSession {
            int[] childSessionIds, boolean sessionApplied, boolean sessionFailed,
            boolean sessionReady, int sessionErrorCode, String sessionErrorMessage,
            PreapprovalDetails preapprovalDetails, DomainSet preVerifiedDomains,
            String packageNameFromApk) {
            String packageNameFromApk, int initialVerificationPolicy,
            int currentVerificationPolicy) {
        this.sessionId = sessionId;
        this.userId = userId;
        this.mOriginalInstallerUid = originalInstallerUid;
@@ -140,6 +143,8 @@ public final class PackageInstallerHistoricalSession {

        this.mPackageName = preapprovalDetails != null ? preapprovalDetails.getPackageName()
                : packageNameFromApk != null ? packageNameFromApk : params.appPackageName;
        this.mInitialVerificationPolicy = initialVerificationPolicy;
        this.mCurrentVerificationPolicy = currentVerificationPolicy;
    }

    void dump(IndentingPrintWriter pw) {
@@ -184,6 +189,8 @@ public final class PackageInstallerHistoricalSession {
        pw.printPair("mPreapprovalDetails", mPreapprovalDetails);
        pw.printPair("mPreVerifiedDomains", mPreVerifiedDomains);
        pw.printPair("mAppPackageName", mPackageName);
        pw.printPair("mInitialVerificationPolicy", mInitialVerificationPolicy);
        pw.printPair("mCurrentVerificationPolicy", mCurrentVerificationPolicy);
        pw.println();

        pw.decreaseIndent();
+50 −11
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static android.content.pm.PackageManager.DELETE_ARCHIVE;
import static android.content.pm.PackageManager.INSTALL_UNARCHIVE_DRAFT;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
import static android.os.UserHandle.USER_SYSTEM;

import static com.android.server.pm.PackageArchiver.isArchivingEnabled;
import static com.android.server.pm.PackageInstallerSession.isValidVerificationPolicy;
@@ -154,7 +155,6 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntPredicate;
import java.util.function.Supplier;

@@ -281,11 +281,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
    };

    /**
     * Default verification policy for incoming installation sessions.
     * TODO(b/360129657): update the default policy.
     * Default verification policy for incoming installation sessions, mapped from userId to policy.
     */
    private final AtomicInteger mVerificationPolicy = new AtomicInteger(
            VERIFICATION_POLICY_BLOCK_FAIL_WARN);
    @GuardedBy("mVerificationPolicyPerUser")
    private final SparseIntArray mVerificationPolicyPerUser = new SparseIntArray(1);
    // TODO(b/360129657): update the default policy.
    private static final int DEFAULT_VERIFICATION_POLICY = VERIFICATION_POLICY_BLOCK_FAIL_WARN;

    private static final class Lifecycle extends SystemService {
        private final PackageInstallerService mPackageInstallerService;
@@ -342,6 +343,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
                context, mInstallThread.getLooper(), new AppStateHelper(context));
        mPackageArchiver = new PackageArchiver(mContext, mPm);
        mVerifierController = new VerifierController(mContext, mInstallHandler);
        synchronized (mVerificationPolicyPerUser) {
            mVerificationPolicyPerUser.put(USER_SYSTEM, DEFAULT_VERIFICATION_POLICY);
        }

        LocalServices.getService(SystemServiceManager.class).startService(
                new Lifecycle(context, this));
@@ -1051,12 +1055,17 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
        InstallSource installSource = InstallSource.create(installerPackageName,
                originatingPackageName, requestedInstallerPackageName, requestedInstallerPackageUid,
                requestedInstallerPackageName, installerAttributionTag, params.packageSource);
        final int verificationPolicy;
        synchronized (mVerificationPolicyPerUser) {
            verificationPolicy = mVerificationPolicyPerUser.get(
                    userId, DEFAULT_VERIFICATION_POLICY);
        }
        session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
                mSilentUpdatePolicy, mInstallThread.getLooper(), mStagingManager, sessionId,
                userId, callingUid, installSource, params, createdMillis, 0L, stageDir, stageCid,
                null, null, false, false, false, false, null, SessionInfo.INVALID_ID,
                false, false, false, PackageManager.INSTALL_UNKNOWN, "", null,
                mVerifierController, mVerificationPolicy.get());
                mVerifierController, verificationPolicy, verificationPolicy);

        synchronized (mSessions) {
            mSessions.put(sessionId, session);
@@ -1882,14 +1891,22 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements

    @Override
    @EnforcePermission(android.Manifest.permission.VERIFICATION_AGENT)
    public @PackageInstaller.VerificationPolicy int getVerificationPolicy() {
    public @PackageInstaller.VerificationPolicy int getVerificationPolicy(int userId) {
        getVerificationPolicy_enforcePermission();
        return mVerificationPolicy.get();
        synchronized (mVerificationPolicyPerUser) {
            if (mVerificationPolicyPerUser.indexOfKey(userId) < 0) {
                throw new IllegalStateException(
                        "Verification policy for user " + userId + " does not exist."
                                + " Does the user exist?");
            }
            return mVerificationPolicyPerUser.get(userId);
        }
    }

    @Override
    @EnforcePermission(android.Manifest.permission.VERIFICATION_AGENT)
    public boolean setVerificationPolicy(@PackageInstaller.VerificationPolicy int policy) {
    public boolean setVerificationPolicy(@PackageInstaller.VerificationPolicy int policy,
            int userId) {
        setVerificationPolicy_enforcePermission();
        final int callingUid = getCallingUid();
        // Only the verifier currently bound by the system can change the policy, except for Shell
@@ -1899,12 +1916,31 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
        if (!isValidVerificationPolicy(policy)) {
            return false;
        }
        if (policy != mVerificationPolicy.get()) {
            mVerificationPolicy.set(policy);
        synchronized (mVerificationPolicyPerUser) {
            if (mVerificationPolicyPerUser.indexOfKey(userId) < 0) {
                throw new IllegalStateException(
                        "Verification policy for user " + userId + " does not exist."
                                + " Does the user exist?");
            }
            if (policy != mVerificationPolicyPerUser.get(userId)) {
                mVerificationPolicyPerUser.put(userId, policy);
            }
        }
        return true;
    }

    void onUserAdded(int userId) {
        synchronized (mVerificationPolicyPerUser) {
            mVerificationPolicyPerUser.put(userId, DEFAULT_VERIFICATION_POLICY);
        }
    }

    void onUserRemoved(int userId) {
        synchronized (mVerificationPolicyPerUser) {
            mVerificationPolicyPerUser.delete(userId);
        }
    }

    private static int getSessionCount(SparseArray<PackageInstallerSession> sessions,
            int installerUid) {
        int count = 0;
@@ -2301,6 +2337,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
        }
        mSilentUpdatePolicy.dump(pw);
        mGentleUpdateHelper.dump(pw);
        synchronized (mVerificationPolicyPerUser) {
            pw.printPair("VerificationPolicyPerUser", mVerificationPolicyPerUser.toString());
        }
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+44 −20
Original line number Diff line number Diff line
@@ -320,7 +320,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private static final String ATTR_APPLICATION_ENABLED_SETTING_PERSISTENT =
            "applicationEnabledSettingPersistent";
    private static final String ATTR_DOMAIN = "domain";
    private static final String ATTR_VERIFICATION_POLICY = "verificationPolicy";
    private static final String ATTR_INITIAL_VERIFICATION_POLICY = "initialVerificationPolicy";
    private static final String ATTR_CURRENT_VERIFICATION_POLICY = "currentVerificationPolicy";

    private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
    private static final int[] EMPTY_CHILD_SESSION_ARRAY = EmptyArray.INT;
@@ -418,10 +419,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private final PackageSessionProvider mSessionProvider;
    private final SilentUpdatePolicy mSilentUpdatePolicy;
    /**
     * The verification policy applied to this session, which might be different from the default
     * verification policy used by the system.
     * The initial verification policy assigned to this session when it was first created.
     */
    private final AtomicInteger mVerificationPolicy;
    private final int mInitialVerificationPolicy;
    /**
     * The active verification policy, which might be different from the initial verification policy
     * assigned to this session or the default policy currently used by the system.
     */
    private final AtomicInteger mCurrentVerificationPolicy;
    /**
     * Note all calls must be done outside {@link #mLock} to prevent lock inversion.
     */
@@ -1182,7 +1187,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            boolean isFailed, boolean isApplied, int sessionErrorCode,
            String sessionErrorMessage, DomainSet preVerifiedDomains,
            @NonNull VerifierController verifierController,
            @PackageInstaller.VerificationPolicy int verificationPolicy) {
            @PackageInstaller.VerificationPolicy int initialVerificationPolicy,
            @PackageInstaller.VerificationPolicy int currentVerificationPolicy) {
        mCallback = callback;
        mContext = context;
        mPm = pm;
@@ -1192,7 +1198,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        mHandler = new Handler(looper, mHandlerCallback);
        mStagingManager = stagingManager;
        mVerifierController = verifierController;
        mVerificationPolicy = new AtomicInteger(verificationPolicy);
        mInitialVerificationPolicy = initialVerificationPolicy;
        mCurrentVerificationPolicy = new AtomicInteger(currentVerificationPolicy);

        this.sessionId = sessionId;
        this.userId = userId;
@@ -1302,7 +1309,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                    mStageDirInUse, mDestroyed, mFds.size(), mBridges.size(), mFinalStatus,
                    mFinalMessage, params, mParentSessionId, getChildSessionIdsLocked(),
                    mSessionApplied, mSessionFailed, mSessionReady, mSessionErrorCode,
                    mSessionErrorMessage, mPreapprovalDetails, mPreVerifiedDomains, mPackageName);
                    mSessionErrorMessage, mPreapprovalDetails, mPreVerifiedDomains, mPackageName,
                    mInitialVerificationPolicy, mCurrentVerificationPolicy.get());
        }
    }

@@ -2887,8 +2895,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            final VerifierCallback verifierCallback = new VerifierCallback();
            if (!mVerifierController.startVerificationSession(mPm::snapshotComputer, userId,
                    sessionId, getPackageName(), Uri.fromFile(stageDir), signingInfo,
                    declaredLibraries, mVerificationPolicy.get(), /* extensionParams= */ null,
                    verifierCallback, /* retry= */ false)) {
                    declaredLibraries, mCurrentVerificationPolicy.get(),
                    /* extensionParams= */ null, verifierCallback, /* retry= */ false)) {
                // A verifier is installed but cannot be connected.
                verifierCallback.onConnectionFailed();
            }
@@ -2967,7 +2975,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
         * verification policy for this session.
         */
        public @PackageInstaller.VerificationPolicy int getVerificationPolicy() {
            return mVerificationPolicy.get();
            return mCurrentVerificationPolicy.get();
        }
        /**
         * Called by the VerifierController when the verifier requests to change the verification
@@ -2977,7 +2985,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            if (!isValidVerificationPolicy(policy)) {
                return false;
            }
            mVerificationPolicy.set(policy);
            mCurrentVerificationPolicy.set(policy);
            return true;
        }
        /**
@@ -3023,7 +3031,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            // TODO: handle extension response
            mHandler.post(() -> {
                if (statusReceived.isVerified()
                        || mVerificationPolicy.get() == VERIFICATION_POLICY_NONE) {
                        || mCurrentVerificationPolicy.get() == VERIFICATION_POLICY_NONE) {
                    // Continue with the rest of the verification and installation.
                    resumeVerify();
                    return;
@@ -3067,13 +3075,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }

        private void handleNonPackageBlockedFailure(Runnable onFailWarning, Runnable onFailClosed) {
            final Runnable r = switch (mVerificationPolicy.get()) {
            final Runnable r = switch (mCurrentVerificationPolicy.get()) {
                case VERIFICATION_POLICY_NONE, VERIFICATION_POLICY_BLOCK_FAIL_OPEN ->
                        PackageInstallerSession.this::resumeVerify;
                case VERIFICATION_POLICY_BLOCK_FAIL_WARN -> onFailWarning;
                case VERIFICATION_POLICY_BLOCK_FAIL_CLOSED -> onFailClosed;
                default -> {
                    Log.wtf(TAG, "Unknown verification policy: " + mVerificationPolicy.get());
                    Log.wtf(TAG, "Unknown verification policy: "
                            + mCurrentVerificationPolicy.get());
                    yield onFailClosed;
                }
            };
@@ -5437,13 +5446,22 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }
    }

    /**
     * @return the initial policy for the verification request assigned to the session when created.
     */
    @VisibleForTesting
    public @PackageInstaller.VerificationPolicy int getInitialVerificationPolicy() {
        assertCallerIsOwnerOrRoot();
        return mInitialVerificationPolicy;
    }

    /**
     * @return the current policy for the verification request associated with this session.
     */
    @VisibleForTesting
    public @PackageInstaller.VerificationPolicy int getVerificationPolicy() {
    public @PackageInstaller.VerificationPolicy int getCurrentVerificationPolicy() {
        assertCallerIsOwnerOrRoot();
        return mVerificationPolicy.get();
        return mCurrentVerificationPolicy.get();
    }

    void setSessionReady() {
@@ -5683,6 +5701,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        if (mPreVerifiedDomains != null) {
            pw.printPair("mPreVerifiedDomains", mPreVerifiedDomains);
        }
        pw.printPair("mInitialVerificationPolicy", mInitialVerificationPolicy);
        pw.printPair("mCurrentVerificationPolicy", mCurrentVerificationPolicy.get());
        pw.println();

        pw.decreaseIndent();
@@ -5907,7 +5927,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            out.attributeInt(null, ATTR_INSTALL_REASON, params.installReason);
            writeBooleanAttribute(out, ATTR_APPLICATION_ENABLED_SETTING_PERSISTENT,
                    params.applicationEnabledSettingPersistent);
            out.attributeInt(null, ATTR_VERIFICATION_POLICY, mVerificationPolicy.get());
            out.attributeInt(null, ATTR_INITIAL_VERIFICATION_POLICY, mInitialVerificationPolicy);
            out.attributeInt(null, ATTR_CURRENT_VERIFICATION_POLICY,
                    mCurrentVerificationPolicy.get());

            final boolean isDataLoader = params.dataLoaderParams != null;
            writeBooleanAttribute(out, ATTR_IS_DATALOADER, isDataLoader);
@@ -6058,8 +6080,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        final boolean sealed = in.getAttributeBoolean(null, ATTR_SEALED, false);
        final int parentSessionId = in.getAttributeInt(null, ATTR_PARENT_SESSION_ID,
                SessionInfo.INVALID_ID);
        final int verificationPolicy = in.getAttributeInt(null, ATTR_VERIFICATION_POLICY,
                VERIFICATION_POLICY_NONE);
        final int initialVerificationPolicy = in.getAttributeInt(null,
                ATTR_INITIAL_VERIFICATION_POLICY, VERIFICATION_POLICY_NONE);
        final int currentVerificationPolicy = in.getAttributeInt(null,
                ATTR_CURRENT_VERIFICATION_POLICY, VERIFICATION_POLICY_NONE);

        final SessionParams params = new SessionParams(
                SessionParams.MODE_INVALID);
@@ -6235,6 +6259,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                stageCid, fileArray, checksumsMap, prepared, committed, destroyed, sealed,
                childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
                sessionErrorCode, sessionErrorMessage, preVerifiedDomains, verifierController,
                verificationPolicy);
                initialVerificationPolicy, currentVerificationPolicy);
    }
}
Loading