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

Commit 83e91711 authored by Rhed Jao's avatar Rhed Jao
Browse files

Add package manager internal api checkUidSignaturesForAllUsers

Starting from U, the PackageManager#checkUidSignatures does not
support to check package signatures for different users. It
returns false if packages cannot be found in the calling user.

This cl adds an internal api checkUidSignaturesForAllUsers for
system modules that need to check package signatures installed
in any users.

Bug: 229684723
Test: atest BlobStoreMultiUserTest
Change-Id: Ib5b3c25dcafe664b31bd737bdb2718c045f845b4
parent 5321abef
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.UserHandle;
import android.util.ArraySet;
@@ -32,6 +33,7 @@ import android.util.DebugUtils;
import android.util.IndentingPrintWriter;

import com.android.internal.util.XmlUtils;
import com.android.server.LocalServices;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -108,7 +110,7 @@ class BlobAccessMode {
        }

        if ((mAccessType & ACCESS_TYPE_SAME_SIGNATURE) != 0) {
            if (checkSignatures(context, callingUid, committerUid)) {
            if (checkSignatures(callingUid, committerUid)) {
                return true;
            }
        }
@@ -133,11 +135,11 @@ class BlobAccessMode {
    /**
     * Compare signatures for two packages of different users.
     */
    private boolean checkSignatures(Context context, int uid1, int uid2) {
    private boolean checkSignatures(int uid1, int uid2) {
        final long token = Binder.clearCallingIdentity();
        try {
            return context.getPackageManager().checkSignatures(uid1, uid2)
                    == PackageManager.SIGNATURE_MATCH;
            return LocalServices.getService(PackageManagerInternal.class)
                    .checkUidSignaturesForAllUsers(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
+12 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager.SignatureResult;
import android.content.pm.SigningDetails.CertCapabilities;
import android.content.pm.overlay.OverlayPaths;
import android.os.Bundle;
@@ -1279,4 +1280,15 @@ public abstract class PackageManagerInternal {
    public abstract void shutdown();

    public abstract DynamicCodeLogger getDynamicCodeLogger();

    /**
     * Compare the signatures of two packages that are installed in different users.
     *
     * @param uid1 First UID whose signature will be compared.
     * @param uid2 Second UID whose signature will be compared.
     * @return {@link PackageManager#SIGNATURE_MATCH} if signatures are matched.
     * @throws SecurityException if the caller does not hold the
     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS}.
     */
    public abstract @SignatureResult int checkUidSignaturesForAllUsers(int uid1, int uid2);
}
+7 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
@@ -623,12 +624,13 @@ public class IntentFirewall {
    }

    boolean signaturesMatch(int uid1, int uid2) {
        final long token = Binder.clearCallingIdentity();
        try {
            IPackageManager pm = AppGlobals.getPackageManager();
            return pm.checkUidSignatures(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
        } catch (RemoteException ex) {
            Slog.e(TAG, "Remote exception while checking signatures", ex);
            return false;
            // Compare signatures of two packages for different users.
            return LocalServices.getService(PackageManagerInternal.class)
                    .checkUidSignaturesForAllUsers(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

+2 −0
Original line number Diff line number Diff line
@@ -397,6 +397,8 @@ public interface Computer extends PackageDataSnapshot {

    int checkUidSignatures(int uid1, int uid2);

    int checkUidSignaturesForAllUsers(int uid1, int uid2);

    boolean hasSigningCertificate(@NonNull String packageName, @NonNull byte[] certificate,
            @PackageManager.CertificateInputType int type);

+30 −7
Original line number Diff line number Diff line
@@ -4263,31 +4263,52 @@ public class ComputerEngine implements Computer {
    @Override
    public int checkUidSignatures(int uid1, int uid2) {
        final int callingUid = Binder.getCallingUid();
        final SigningDetails p1SigningDetails = getSigningDetailsAndFilterAccess(uid1, callingUid);
        final SigningDetails p2SigningDetails = getSigningDetailsAndFilterAccess(uid2, callingUid);
        final int callingUserId = UserHandle.getUserId(callingUid);
        final SigningDetails p1SigningDetails =
                getSigningDetailsAndFilterAccess(uid1, callingUid, callingUserId);
        final SigningDetails p2SigningDetails =
                getSigningDetailsAndFilterAccess(uid2, callingUid, callingUserId);
        if (p1SigningDetails == null || p2SigningDetails == null) {
            return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
        }
        return checkSignaturesInternal(p1SigningDetails, p2SigningDetails);
    }

    private SigningDetails getSigningDetailsAndFilterAccess(int uid, int callingUid) {
    @Override
    public int checkUidSignaturesForAllUsers(int uid1, int uid2) {
        final int callingUid = Binder.getCallingUid();
        final int userId1 = UserHandle.getUserId(uid1);
        final int userId2 = UserHandle.getUserId(uid2);
        enforceCrossUserPermission(callingUid, userId1, false /* requireFullPermission */,
                false /* checkShell */, "checkUidSignaturesForAllUsers");
        enforceCrossUserPermission(callingUid, userId2, false /* requireFullPermission */,
                false /* checkShell */, "checkUidSignaturesForAllUsers");
        final SigningDetails p1SigningDetails =
                getSigningDetailsAndFilterAccess(uid1, callingUid, userId1);
        final SigningDetails p2SigningDetails =
                getSigningDetailsAndFilterAccess(uid2, callingUid, userId2);
        if (p1SigningDetails == null || p2SigningDetails == null) {
            return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
        }
        return checkSignaturesInternal(p1SigningDetails, p2SigningDetails);
    }

    private SigningDetails getSigningDetailsAndFilterAccess(int uid, int callingUid, int userId) {
        // Map to base uids.
        final int appId = UserHandle.getAppId(uid);
        final int callingUserId = UserHandle.getUserId(callingUid);
        final Object obj = mSettings.getSettingBase(appId);
        if (obj == null) {
            return null;
        }
        if (obj instanceof SharedUserSetting) {
            final SharedUserSetting sus = (SharedUserSetting) obj;
            if (shouldFilterApplicationIncludingUninstalled(sus, callingUid, callingUserId)) {
            if (shouldFilterApplicationIncludingUninstalled(sus, callingUid, userId)) {
                return null;
            }
            return sus.signatures.mSigningDetails;
        } else if (obj instanceof PackageSetting) {
            final PackageSetting ps = (PackageSetting) obj;
            if (shouldFilterApplicationIncludingUninstalled(ps, callingUid, callingUserId)) {
            if (shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)) {
                return null;
            }
            return ps.getSigningDetails();
@@ -4356,7 +4377,9 @@ public class ComputerEngine implements Computer {
    public boolean hasUidSigningCertificate(int uid, @NonNull byte[] certificate,
            @PackageManager.CertificateInputType int type) {
        final int callingUid = Binder.getCallingUid();
        final SigningDetails signingDetails = getSigningDetailsAndFilterAccess(uid, callingUid);
        final int callingUserId = UserHandle.getUserId(callingUid);
        final SigningDetails signingDetails =
                getSigningDetailsAndFilterAccess(uid, callingUid, callingUserId);
        if (signingDetails == null) {
            return false;
        }
Loading