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
This commit is contained in:
Rhed Jao
2022-05-09 19:24:07 +08:00
parent 5321abef41
commit 83e91711f2
6 changed files with 62 additions and 16 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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