diff options
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 |