diff options
| author | 2022-05-09 19:24:07 +0800 | |
|---|---|---|
| committer | 2022-05-10 11:57:56 +0800 | |
| commit | 83e91711f24c7704cfd84d863fc22c3fe83d15d4 (patch) | |
| tree | a5445645f21c227c07cab561a78a05667b8c9da0 | |
| parent | 5321abef41e5130340c9612518014dd9d7664661 (diff) | |
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
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 83ef21e7528b..b0c295c331d7 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 c45a87174924..9b2c10f6130c 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 bb8a74493a16..c8a3ee6b1be6 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 bcffd65d3424..2657be3a97d9 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 edbaba5faa2d..6e772b23bf1b 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 4a3b79e41de1..a224b2258d54 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 |