Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 992ba2dd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Resolve the issue that when there are no integrity rule files pushed,...

Merge "Resolve the issue that when there are no integrity rule files pushed, we do not evaluate the rules based on android manifest."
parents 97e66d02 d4c9af8d
Loading
Loading
Loading
Loading
+3 −13
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
import android.util.Slog;
import android.util.StatsLog;

@@ -158,8 +157,7 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {

    @Override
    public void updateRuleSet(
            String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver)
            throws RemoteException {
            String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver) {
        String ruleProvider = getCallerPackageNameOrThrow();

        mHandler.post(
@@ -190,7 +188,7 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
    }

    @Override
    public String getCurrentRuleSetVersion() throws RemoteException {
    public String getCurrentRuleSetVersion() {
        getCallerPackageNameOrThrow();

        RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
@@ -200,7 +198,7 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
    }

    @Override
    public String getCurrentRuleSetProvider() throws RemoteException {
    public String getCurrentRuleSetProvider() {
        getCallerPackageNameOrThrow();

        RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
@@ -212,14 +210,6 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
    private void handleIntegrityVerification(Intent intent) {
        int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);

        // Fail early if we don't have any rules at all.
        if (!mIntegrityFileManager.initialized()) {
            Slog.i(TAG, "Rules not initialized. Skipping integrity check.");
            mPackageManagerInternal.setIntegrityVerificationResult(
                    verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
            return;
        }

        try {
            Slog.i(TAG, "Received integrity verification intent " + intent.toString());
            Slog.i(TAG, "Extras " + intent.getExtras());
+5 −0
Original line number Diff line number Diff line
@@ -76,6 +76,11 @@ public class RuleEvaluationEngine {
    }

    private List<Rule> loadRules(AppInstallMetadata appInstallMetadata) {
        if (!mIntegrityFileManager.initialized()) {
            Slog.w(TAG, "Integrity rule files are not available. Evaluating only manifest rules.");
            return new ArrayList<>();
        }

        try {
            return mIntegrityFileManager.readRules(appInstallMetadata);
        } catch (Exception e) {
+5 −29
Original line number Diff line number Diff line
@@ -32,11 +32,9 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.internal.verification.VerificationModeFactory.times;

import android.content.BroadcastReceiver;
import android.content.Context;
@@ -59,7 +57,6 @@ import android.os.Message;
import androidx.test.InstrumentationRegistry;

import com.android.internal.R;
import com.android.server.LocalServices;
import com.android.server.integrity.engine.RuleEvaluationEngine;
import com.android.server.integrity.model.IntegrityCheckResult;
import com.android.server.testutils.TestUtils;
@@ -147,29 +144,8 @@ public class AppIntegrityManagerServiceImplTest {
        when(mIntegrityFileManager.initialized()).thenReturn(true);
    }

    // This is not a test of the class, but more of a safeguard that we don't block any install in
    // the default case. This is needed because we don't have any emergency kill switch to disable
    // this component.
    @Test
    public void default_allow() throws Exception {
        LocalServices.removeServiceForTest(PackageManagerInternal.class);
        LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
        mService = AppIntegrityManagerServiceImpl.create(mMockContext);
        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext, times(2))
                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
        Intent intent = makeVerificationIntent();

        broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);

        // Since we are not mocking handler in this case, we must wait.
        // 2 seconds should be a sensible timeout.
        Thread.sleep(2000);
        verify(mPackageManagerInternal)
                .setIntegrityVerificationResult(
                        1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
    }
    // TODO(b/148370598): Implement a test to validate that allow response is retuned when the test
    //    request times out.

    @Test
    public void updateRuleSet_notAuthorized() throws Exception {
@@ -381,10 +357,10 @@ public class AppIntegrityManagerServiceImplTest {
        broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
        runJobInHandler();

        // The evaluation will still run since we still evaluate manifest based rules.
        verify(mPackageManagerInternal)
                .setIntegrityVerificationResult(
                        1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
        verify(mSpyPackageManager, never()).getPackageArchiveInfo(any(), anyInt());
    }

    @Test
@@ -432,8 +408,8 @@ public class AppIntegrityManagerServiceImplTest {

    private Intent makeVerificationIntent() throws Exception {
        PackageInfo packageInfo =
                mRealContext.getPackageManager().getPackageInfo(TEST_FRAMEWORK_PACKAGE,
                        PackageManager.GET_SIGNATURES);
                mRealContext.getPackageManager()
                        .getPackageInfo(TEST_FRAMEWORK_PACKAGE, PackageManager.GET_SIGNATURES);
        doReturn(packageInfo)
                .when(mSpyPackageManager)
                .getPackageInfo(eq(INSTALLER), anyInt());
+110 −103
Original line number Diff line number Diff line
@@ -16,12 +16,12 @@

package com.android.server.integrity.engine;

import static org.junit.Assert.assertEquals;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import android.content.integrity.AppInstallMetadata;
import android.content.integrity.Rule;

import com.android.server.integrity.IntegrityFileManager;
import com.android.server.integrity.model.IntegrityCheckResult;
@@ -36,7 +36,6 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RunWith(JUnit4.class)
@@ -68,33 +67,28 @@ public class RuleEvaluationEngineTest {
    public void testAllowedInstallers_empty() {
        Map<String, String> allowedInstallers = Collections.emptyMap();

        assertEquals(
                IntegrityCheckResult.Effect.ALLOW,
                mEngine.evaluate(
        AppInstallMetadata appInstallMetadata1 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificate(INSTALLER_1_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
        assertEquals(
                IntegrityCheckResult.Effect.ALLOW,
                mEngine.evaluate(
                        .build();
        AppInstallMetadata appInstallMetadata2 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_2)
                        .setInstallerCertificate(INSTALLER_2_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
        assertEquals(
                IntegrityCheckResult.Effect.ALLOW,
                mEngine.evaluate(
                        .build();
        AppInstallMetadata appInstallMetadata3 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(RANDOM_INSTALLER)
                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
                        .build();

        assertThat(mEngine.evaluate(appInstallMetadata1, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
        assertThat(mEngine.evaluate(appInstallMetadata2, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
        assertThat(mEngine.evaluate(appInstallMetadata3, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
    }

    @Test
@@ -102,87 +96,100 @@ public class RuleEvaluationEngineTest {
        Map<String, String> allowedInstallers =
                Collections.singletonMap(INSTALLER_1, INSTALLER_1_CERT);

        assertEquals(
                IntegrityCheckResult.Effect.ALLOW,
                mEngine.evaluate(
        AppInstallMetadata appInstallMetadata1 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificate(INSTALLER_1_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
        assertEquals(
                IntegrityCheckResult.Effect.DENY,
                mEngine.evaluate(
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata1, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata2 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(RANDOM_INSTALLER)
                        .setInstallerCertificate(INSTALLER_1_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
        assertEquals(
                IntegrityCheckResult.Effect.DENY,
                mEngine.evaluate(
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata2, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.DENY);

        AppInstallMetadata appInstallMetadata3 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
        assertEquals(
                IntegrityCheckResult.Effect.DENY,
                mEngine.evaluate(
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata3, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.DENY);

        AppInstallMetadata appInstallMetadata4 =
                getAppInstallMetadataBuilder()
                                .setInstallerName(RANDOM_INSTALLER)
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificate(RANDOM_INSTALLER_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata4, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.DENY);
    }

    @Test
    public void testAllowedInstallers_multipleElement() {
        List<Rule> rules = new ArrayList<>();
        Map<String, String> allowedInstallers = new HashMap<>(2);
        allowedInstallers.put(INSTALLER_1, INSTALLER_1_CERT);
        allowedInstallers.put(INSTALLER_2, INSTALLER_2_CERT);

        assertEquals(
                IntegrityCheckResult.Effect.ALLOW,
                mEngine.evaluate(
        AppInstallMetadata appInstallMetadata1 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificate(INSTALLER_1_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
        assertEquals(
                IntegrityCheckResult.Effect.ALLOW,
                mEngine.evaluate(
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata1, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata2 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_2)
                        .setInstallerCertificate(INSTALLER_2_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
        assertEquals(
                IntegrityCheckResult.Effect.DENY,
                mEngine.evaluate(
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata2, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata3 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificate(INSTALLER_2_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
        assertEquals(
                IntegrityCheckResult.Effect.DENY,
                mEngine.evaluate(
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata3, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.DENY);

        AppInstallMetadata appInstallMetadata4 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_2)
                        .setInstallerCertificate(INSTALLER_1_CERT)
                                .build(),
                        allowedInstallers)
                        .getEffect());
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata4, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.DENY);
    }

    @Test
    public void manifestBasedRuleEvaluationWorksEvenWhenIntegrityFilesAreUnavailable() {
        when(mIntegrityFileManager.initialized()).thenReturn(false);

        Map<String, String> allowedInstallers =
                Collections.singletonMap(INSTALLER_1, INSTALLER_1_CERT);

        AppInstallMetadata appInstallMetadata1 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificate(INSTALLER_1_CERT)
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata1, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata2 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(RANDOM_INSTALLER)
                        .setInstallerCertificate(INSTALLER_1_CERT)
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata2, allowedInstallers).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.DENY);
    }

    /** Returns a builder with all fields filled with some dummy data. */