From e466493f72c05a607fc3de1fac9f8d943e5f6729 Mon Sep 17 00:00:00 2001 From: Winson Chiu Date: Tue, 14 Dec 2021 18:58:30 +0000 Subject: [PATCH] Verify querent for printing app links state Verifies that printing domain verification state asserts that the caller is an approved querent, to match the getDomainVerificationInfo Java API. Also allows callers with the DUMP permission to be a querent, so that dumpsys package still works. Test: atest DomainVerificationEnforcerTest Change-Id: I9ad409ba15ce1a358ca8c0e047444a2fa6d2140b --- .../com/android/server/pm/ComputerEngine.java | 2 +- .../domain/DomainVerificationEnforcer.java | 7 +++-- .../domain/DomainVerificationService.java | 1 + .../domain/DomainVerificationEnforcerTest.kt | 29 +++++++++++++++++-- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 59250c5d452d1..33352f78bb936 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -3156,7 +3156,7 @@ public class ComputerEngine implements Computer { try { mDomainVerificationManager.printState(writer, packageName, UserHandle.USER_ALL, mSettings::getPackage); - } catch (PackageManager.NameNotFoundException e) { + } catch (Exception e) { pw.println("Failure printing domain verification information"); Slog.e(TAG, "Failure printing domain verification information", e); } diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationEnforcer.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationEnforcer.java index 0b48b5c6dd705..2208e3c02c4d1 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationEnforcer.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationEnforcer.java @@ -70,8 +70,11 @@ public class DomainVerificationEnforcer { break; default: if (!proxy.isCallerVerifier(callingUid)) { - throw new SecurityException( - "Caller is not allowed to query domain verification state"); + mContext.enforcePermission(android.Manifest.permission.DUMP, + Binder.getCallingPid(), callingUid, + "Caller " + callingUid + + " is not allowed to query domain verification state"); + break; } mContext.enforcePermission(android.Manifest.permission.QUERY_ALL_PACKAGES, diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java index 661e67d424aea..970d6d31127f6 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java @@ -1197,6 +1197,7 @@ public class DomainVerificationService extends SystemService @Nullable @UserIdInt Integer userId, @NonNull Function pkgSettingFunction) throws NameNotFoundException { + mEnforcer.assertApprovedQuerent(mConnection.getCallingUid(), mProxy); synchronized (mLock) { mDebug.printState(writer, packageName, userId, pkgSettingFunction, mAttachedPkgStates); } diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt index d1d7cc6422c33..089e9db9a7559 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt @@ -19,6 +19,7 @@ package com.android.server.pm.test.verify.domain import android.content.Context import android.content.Intent import android.content.pm.PackageManager +import android.content.pm.SigningDetails import android.content.pm.parsing.component.ParsedActivityImpl import android.content.pm.parsing.component.ParsedIntentInfoImpl import android.content.pm.verify.domain.DomainVerificationManager @@ -26,6 +27,7 @@ import android.content.pm.verify.domain.DomainVerificationState import android.os.Build import android.os.Process import android.util.ArraySet +import android.util.IndentingPrintWriter import android.util.SparseArray import androidx.test.platform.app.InstrumentationRegistry import com.android.server.pm.parsing.pkg.AndroidPackage @@ -46,6 +48,7 @@ import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyLong import org.mockito.Mockito.anyString import org.mockito.Mockito.eq +import org.mockito.Mockito.mock import org.mockito.Mockito.verifyNoMoreInteractions import java.util.UUID import java.util.concurrent.atomic.AtomicBoolean @@ -204,6 +207,14 @@ class DomainVerificationEnforcerTest { service(Type.QUERENT, "getInfo") { getDomainVerificationInfo(it.targetPackageName) }, + service(Type.QUERENT, "printState") { + printState(mock(IndentingPrintWriter::class.java), null, null) + }, + service(Type.QUERENT, "printStateInternal") { + printState(mock(IndentingPrintWriter::class.java), null, null) { + mockPkgState(it, UUID.randomUUID()) + } + }, service(Type.VERIFIER, "setStatus") { setDomainVerificationStatus( it.targetDomainSetId, @@ -311,6 +322,7 @@ class DomainVerificationEnforcerTest { } ) } + whenever(signingDetails) { SigningDetails.UNKNOWN } } fun mockPkgState(packageName: String, domainSetId: UUID) = @@ -327,6 +339,7 @@ class DomainVerificationEnforcerTest { } } whenever(isSystem) { false } + whenever(signingDetails) { SigningDetails.UNKNOWN } } } @@ -373,6 +386,7 @@ class DomainVerificationEnforcerTest { val allowUserState = AtomicBoolean(false) val allowPreferredApps = AtomicBoolean(false) val allowQueryAll = AtomicBoolean(false) + val allowDump = AtomicBoolean(false) val context: Context = mockThrowOnUnmocked { initPermission( allowUserState, @@ -383,6 +397,7 @@ class DomainVerificationEnforcerTest { android.Manifest.permission.SET_PREFERRED_APPLICATIONS ) initPermission(allowQueryAll, android.Manifest.permission.QUERY_ALL_PACKAGES) + initPermission(allowDump, android.Manifest.permission.DUMP) } val target = params.construct(context) @@ -409,6 +424,10 @@ class DomainVerificationEnforcerTest { allowQueryAll.set(true) assertFails { runMethod(target, NON_VERIFIER_UID) } + + allowDump.set(true) + + runMethod(target, NON_VERIFIER_UID) } private fun approvedVerifier() { @@ -794,8 +813,12 @@ class DomainVerificationEnforcerTest { } val valueAsInt = value as? Int - if (valueAsInt != null && valueAsInt == DomainVerificationManager.STATUS_OK) { - throw AssertionError("Expected call to return false, was $value") + if (valueAsInt != null) { + if (valueAsInt == DomainVerificationManager.STATUS_OK) { + throw AssertionError("Expected call to return false, was $value") + } + } else { + throw AssertionError("Expected call to fail") } } catch (e: SecurityException) { } catch (e: PackageManager.NameNotFoundException) { @@ -807,7 +830,7 @@ class DomainVerificationEnforcerTest { // System/shell only INTERNAL, - // INTERNAL || non-legacy domain verification agent + // INTERNAL || non-legacy domain verification agent || DUMP permission QUERENT, // INTERNAL || domain verification agent