From 83e91711f24c7704cfd84d863fc22c3fe83d15d4 Mon Sep 17 00:00:00 2001 From: Rhed Jao Date: Mon, 9 May 2022 19:24:07 +0800 Subject: [PATCH] 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 --- .../android/server/blob/BlobAccessMode.java | 10 +++-- .../content/pm/PackageManagerInternal.java | 12 ++++++ .../server/firewall/IntentFirewall.java | 12 +++--- .../java/com/android/server/pm/Computer.java | 2 + .../com/android/server/pm/ComputerEngine.java | 37 +++++++++++++++---- .../server/pm/PackageManagerInternalBase.java | 5 +++ 6 files changed, 62 insertions(+), 16 deletions(-) diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java index 83ef21e7528b5..b0c295c331d79 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java @@ -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); } diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index c45a871749247..9b2c10f6130c2 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -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); } diff --git a/services/core/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java index bb8a74493a16a..c8a3ee6b1be6e 100644 --- a/services/core/java/com/android/server/firewall/IntentFirewall.java +++ b/services/core/java/com/android/server/firewall/IntentFirewall.java @@ -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); } } diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java index bcffd65d34240..2657be3a97d9f 100644 --- a/services/core/java/com/android/server/pm/Computer.java +++ b/services/core/java/com/android/server/pm/Computer.java @@ -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); diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index edbaba5faa2d7..6e772b23bf1b6 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -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; } diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java index 4a3b79e41de14..a224b2258d548 100644 --- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java +++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java @@ -721,6 +721,11 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal { return snapshot().isUidPrivileged(uid); } + @Override + public int checkUidSignaturesForAllUsers(int uid1, int uid2) { + return snapshot().checkUidSignaturesForAllUsers(uid1, uid2); + } + @NonNull @Override @Deprecated