From 739016197a00c2dbe6702fc2d50325b0c303eea9 Mon Sep 17 00:00:00 2001 From: Khaled Abdelmohsen Date: Tue, 21 Jan 2020 21:12:21 +0000 Subject: [PATCH] Skip integrity verification for verifiers Test: atest FrameworksServicesTests:AppIntegrityManagerServiceImplTest Change-Id: I1c86cb2ece9943699081a7e98644ecc1bec58b30 --- .../AppIntegrityManagerServiceImpl.java | 24 +++++++- .../AppIntegrityManagerServiceImplTest.java | 55 +++++++++++++++++-- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java index b1639a948ffc6..dec3cda4ae639 100644 --- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java +++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java @@ -220,7 +220,17 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { return; } + String ruleProvider = getCallerPackageName(); String installerPackageName = getInstallerPackageName(intent); + + // Skip integrity verification if the verifier is doing the install. + if (ruleProvider != null && ruleProvider.equals(installerPackageName)) { + Slog.i(TAG, "Verifier doing the install. Skipping integrity check."); + mPackageManagerInternal.setIntegrityVerificationResult( + verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW); + return; + } + String appCert = getCertificateFingerprint(packageInfo); AppInstallMetadata.Builder builder = new AppInstallMetadata.Builder(); @@ -518,6 +528,16 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { } private String getCallerPackageNameOrThrow() { + String callerPackageName = getCallerPackageName(); + if (callerPackageName == null) { + throw new SecurityException( + "Only system packages specified in config_integrityRuleProviderPackages are" + + " allowed to call this method."); + } + return callerPackageName; + } + + private String getCallerPackageName() { final String[] allowedRuleProviders = mContext.getResources() .getStringArray(R.array.config_integrityRuleProviderPackages); @@ -537,9 +557,7 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { Slog.i(TAG, "Rule provider package " + packageName + " not installed."); } } - throw new SecurityException( - "Only system packages specified in config_integrityRuleProviderPackages are" - + " allowed to call this method."); + return null; } private boolean isSystemApp(String packageName) { diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java index 604efc4949fe2..a6af9a99788f3 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java @@ -92,7 +92,7 @@ public class AppIntegrityManagerServiceImplTest { private static final String PACKAGE_NAME = "com.test.app"; private static final int VERSION_CODE = 100; - private static final String INSTALLER = TEST_FRAMEWORK_PACKAGE; + private static final String INSTALLER = "com.long.random.test.installer.name"; // These are obtained by running the test and checking logcat. private static final String APP_CERT = "301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA"; @@ -100,7 +100,7 @@ public class AppIntegrityManagerServiceImplTest { "301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA"; // We use SHA256 for package names longer than 32 characters. private static final String INSTALLER_SHA256 = - "786933C28839603EB48C50B2A688DC6BE52C833627CB2731FF8466A2AE9F94CD"; + "30F41A7CBF96EE736A54DD6DF759B50ED3CC126ABCEF694E167C324F5976C227"; private static final String PLAY_STORE_PKG = "com.android.vending"; private static final String ADB_INSTALLER = "adb"; @@ -140,7 +140,7 @@ public class AppIntegrityManagerServiceImplTest { // setup mocks to prevent NPE when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager); when(mMockContext.getResources()).thenReturn(mMockResources); - when(mMockResources.getStringArray(anyInt())).thenReturn(new String[] {}); + when(mMockResources.getStringArray(anyInt())).thenReturn(new String[]{}); when(mIntegrityFileManager.initialized()).thenReturn(true); } @@ -267,6 +267,8 @@ public class AppIntegrityManagerServiceImplTest { @Test public void broadcastReceiverRegistration() throws Exception { + whitelistUsAsRuleProvider(); + makeUsSystemApp(); ArgumentCaptor intentFilterCaptor = ArgumentCaptor.forClass(IntentFilter.class); @@ -281,6 +283,8 @@ public class AppIntegrityManagerServiceImplTest { @Test public void handleBroadcast_correctArgs() throws Exception { + whitelistUsAsRuleProvider(); + makeUsSystemApp(); ArgumentCaptor broadcastReceiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); verify(mMockContext) @@ -314,6 +318,8 @@ public class AppIntegrityManagerServiceImplTest { @Test public void handleBroadcast_allow() throws Exception { + whitelistUsAsRuleProvider(); + makeUsSystemApp(); ArgumentCaptor broadcastReceiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); verify(mMockContext) @@ -331,6 +337,8 @@ public class AppIntegrityManagerServiceImplTest { @Test public void handleBroadcast_reject() throws Exception { + whitelistUsAsRuleProvider(); + makeUsSystemApp(); ArgumentCaptor broadcastReceiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); verify(mMockContext) @@ -354,6 +362,8 @@ public class AppIntegrityManagerServiceImplTest { @Test public void handleBroadcast_notInitialized() throws Exception { + whitelistUsAsRuleProvider(); + makeUsSystemApp(); when(mIntegrityFileManager.initialized()).thenReturn(false); ArgumentCaptor broadcastReceiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); @@ -371,10 +381,30 @@ public class AppIntegrityManagerServiceImplTest { verify(mSpyPackageManager, never()).getPackageArchiveInfo(any(), anyInt()); } + @Test + public void verifierAsInstaller_skipIntegrityVerification() throws Exception { + whitelistUsAsRuleProvider(); + makeUsSystemApp(); + ArgumentCaptor broadcastReceiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + verify(mMockContext) + .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); + Intent intent = makeVerificationIntent(TEST_FRAMEWORK_PACKAGE); + when(mRuleEvaluationEngine.evaluate(any(), any())).thenReturn( + IntegrityCheckResult.deny(/* rule= */ null)); + + broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent); + runJobInHandler(); + + verify(mPackageManagerInternal) + .setIntegrityVerificationResult( + 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW); + } + private void whitelistUsAsRuleProvider() { Resources mockResources = mock(Resources.class); when(mockResources.getStringArray(R.array.config_integrityRuleProviderPackages)) - .thenReturn(new String[] {TEST_FRAMEWORK_PACKAGE}); + .thenReturn(new String[]{TEST_FRAMEWORK_PACKAGE}); when(mMockContext.getResources()).thenReturn(mockResources); } @@ -395,15 +425,28 @@ public class AppIntegrityManagerServiceImplTest { } private Intent makeVerificationIntent() throws Exception { + PackageInfo packageInfo = + mRealContext.getPackageManager().getPackageInfo(TEST_FRAMEWORK_PACKAGE, + PackageManager.GET_SIGNATURES); + doReturn(packageInfo) + .when(mSpyPackageManager) + .getPackageInfo(eq(INSTALLER), anyInt()); + doReturn(1) + .when(mSpyPackageManager) + .getPackageUid(eq(INSTALLER), anyInt()); + return makeVerificationIntent(INSTALLER); + } + + private Intent makeVerificationIntent(String installer) throws Exception { Intent intent = new Intent(); intent.setDataAndType(Uri.fromFile(mTestApk), PACKAGE_MIME_TYPE); intent.setAction(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION); intent.putExtra(EXTRA_VERIFICATION_ID, 1); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, PACKAGE_NAME); - intent.putExtra(EXTRA_VERIFICATION_INSTALLER_PACKAGE, INSTALLER); + intent.putExtra(EXTRA_VERIFICATION_INSTALLER_PACKAGE, installer); intent.putExtra( EXTRA_VERIFICATION_INSTALLER_UID, - mRealContext.getPackageManager().getPackageUid(INSTALLER, /* flags= */ 0)); + mMockContext.getPackageManager().getPackageUid(installer, /* flags= */ 0)); intent.putExtra(Intent.EXTRA_VERSION_CODE, VERSION_CODE); return intent; }