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
This commit is contained in:
Winson Chiu
2021-12-14 18:58:30 +00:00
committed by Winson
parent ea2b19eb98
commit e466493f72
4 changed files with 33 additions and 6 deletions

View File

@@ -3156,7 +3156,7 @@ public class ComputerEngine implements Computer {
try { try {
mDomainVerificationManager.printState(writer, packageName, mDomainVerificationManager.printState(writer, packageName,
UserHandle.USER_ALL, mSettings::getPackage); UserHandle.USER_ALL, mSettings::getPackage);
} catch (PackageManager.NameNotFoundException e) { } catch (Exception e) {
pw.println("Failure printing domain verification information"); pw.println("Failure printing domain verification information");
Slog.e(TAG, "Failure printing domain verification information", e); Slog.e(TAG, "Failure printing domain verification information", e);
} }

View File

@@ -70,8 +70,11 @@ public class DomainVerificationEnforcer {
break; break;
default: default:
if (!proxy.isCallerVerifier(callingUid)) { if (!proxy.isCallerVerifier(callingUid)) {
throw new SecurityException( mContext.enforcePermission(android.Manifest.permission.DUMP,
"Caller is not allowed to query domain verification state"); Binder.getCallingPid(), callingUid,
"Caller " + callingUid
+ " is not allowed to query domain verification state");
break;
} }
mContext.enforcePermission(android.Manifest.permission.QUERY_ALL_PACKAGES, mContext.enforcePermission(android.Manifest.permission.QUERY_ALL_PACKAGES,

View File

@@ -1197,6 +1197,7 @@ public class DomainVerificationService extends SystemService
@Nullable @UserIdInt Integer userId, @Nullable @UserIdInt Integer userId,
@NonNull Function<String, PackageStateInternal> pkgSettingFunction) @NonNull Function<String, PackageStateInternal> pkgSettingFunction)
throws NameNotFoundException { throws NameNotFoundException {
mEnforcer.assertApprovedQuerent(mConnection.getCallingUid(), mProxy);
synchronized (mLock) { synchronized (mLock) {
mDebug.printState(writer, packageName, userId, pkgSettingFunction, mAttachedPkgStates); mDebug.printState(writer, packageName, userId, pkgSettingFunction, mAttachedPkgStates);
} }

View File

@@ -19,6 +19,7 @@ package com.android.server.pm.test.verify.domain
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.SigningDetails
import android.content.pm.parsing.component.ParsedActivityImpl import android.content.pm.parsing.component.ParsedActivityImpl
import android.content.pm.parsing.component.ParsedIntentInfoImpl import android.content.pm.parsing.component.ParsedIntentInfoImpl
import android.content.pm.verify.domain.DomainVerificationManager 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.Build
import android.os.Process import android.os.Process
import android.util.ArraySet import android.util.ArraySet
import android.util.IndentingPrintWriter
import android.util.SparseArray import android.util.SparseArray
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.pm.parsing.pkg.AndroidPackage 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.anyLong
import org.mockito.Mockito.anyString import org.mockito.Mockito.anyString
import org.mockito.Mockito.eq import org.mockito.Mockito.eq
import org.mockito.Mockito.mock
import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.verifyNoMoreInteractions
import java.util.UUID import java.util.UUID
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@@ -204,6 +207,14 @@ class DomainVerificationEnforcerTest {
service(Type.QUERENT, "getInfo") { service(Type.QUERENT, "getInfo") {
getDomainVerificationInfo(it.targetPackageName) 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") { service(Type.VERIFIER, "setStatus") {
setDomainVerificationStatus( setDomainVerificationStatus(
it.targetDomainSetId, it.targetDomainSetId,
@@ -311,6 +322,7 @@ class DomainVerificationEnforcerTest {
} }
) )
} }
whenever(signingDetails) { SigningDetails.UNKNOWN }
} }
fun mockPkgState(packageName: String, domainSetId: UUID) = fun mockPkgState(packageName: String, domainSetId: UUID) =
@@ -327,6 +339,7 @@ class DomainVerificationEnforcerTest {
} }
} }
whenever(isSystem) { false } whenever(isSystem) { false }
whenever(signingDetails) { SigningDetails.UNKNOWN }
} }
} }
@@ -373,6 +386,7 @@ class DomainVerificationEnforcerTest {
val allowUserState = AtomicBoolean(false) val allowUserState = AtomicBoolean(false)
val allowPreferredApps = AtomicBoolean(false) val allowPreferredApps = AtomicBoolean(false)
val allowQueryAll = AtomicBoolean(false) val allowQueryAll = AtomicBoolean(false)
val allowDump = AtomicBoolean(false)
val context: Context = mockThrowOnUnmocked { val context: Context = mockThrowOnUnmocked {
initPermission( initPermission(
allowUserState, allowUserState,
@@ -383,6 +397,7 @@ class DomainVerificationEnforcerTest {
android.Manifest.permission.SET_PREFERRED_APPLICATIONS android.Manifest.permission.SET_PREFERRED_APPLICATIONS
) )
initPermission(allowQueryAll, android.Manifest.permission.QUERY_ALL_PACKAGES) initPermission(allowQueryAll, android.Manifest.permission.QUERY_ALL_PACKAGES)
initPermission(allowDump, android.Manifest.permission.DUMP)
} }
val target = params.construct(context) val target = params.construct(context)
@@ -409,6 +424,10 @@ class DomainVerificationEnforcerTest {
allowQueryAll.set(true) allowQueryAll.set(true)
assertFails { runMethod(target, NON_VERIFIER_UID) } assertFails { runMethod(target, NON_VERIFIER_UID) }
allowDump.set(true)
runMethod(target, NON_VERIFIER_UID)
} }
private fun approvedVerifier() { private fun approvedVerifier() {
@@ -794,8 +813,12 @@ class DomainVerificationEnforcerTest {
} }
val valueAsInt = value as? Int val valueAsInt = value as? Int
if (valueAsInt != null && valueAsInt == DomainVerificationManager.STATUS_OK) { if (valueAsInt != null) {
throw AssertionError("Expected call to return false, was $value") 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: SecurityException) {
} catch (e: PackageManager.NameNotFoundException) { } catch (e: PackageManager.NameNotFoundException) {
@@ -807,7 +830,7 @@ class DomainVerificationEnforcerTest {
// System/shell only // System/shell only
INTERNAL, INTERNAL,
// INTERNAL || non-legacy domain verification agent // INTERNAL || non-legacy domain verification agent || DUMP permission
QUERENT, QUERENT,
// INTERNAL || domain verification agent // INTERNAL || domain verification agent