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

Commit 21f7b723 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Remove RuleEvaluationEngine from AppIntegrityManagerService." into main am: 69741ced

parents affda051 69741ced
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ import com.android.internal.pm.parsing.PackageParser2;
import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
import com.android.internal.util.ArrayUtils;
import com.android.server.LocalServices;
import com.android.server.integrity.engine.RuleEvaluationEngine;
import com.android.server.integrity.model.IntegrityCheckResult;
import com.android.server.integrity.model.RuleMetadata;
import com.android.server.pm.PackageManagerServiceUtils;
@@ -130,7 +129,6 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
    private final Handler mHandler;
    private final PackageManagerInternal mPackageManagerInternal;
    private final Supplier<PackageParser2> mParserSupplier;
    private final RuleEvaluationEngine mEvaluationEngine;
    private final IntegrityFileManager mIntegrityFileManager;

    /** Create an instance of {@link AppIntegrityManagerServiceImpl}. */
@@ -142,7 +140,6 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
                context,
                LocalServices.getService(PackageManagerInternal.class),
                PackageParserUtils::forParsingFileWithDefaults,
                RuleEvaluationEngine.getRuleEvaluationEngine(),
                IntegrityFileManager.getInstance(),
                handlerThread.getThreadHandler());
    }
@@ -152,13 +149,11 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
            Context context,
            PackageManagerInternal packageManagerInternal,
            Supplier<PackageParser2> parserSupplier,
            RuleEvaluationEngine evaluationEngine,
            IntegrityFileManager integrityFileManager,
            Handler handler) {
        mContext = context;
        mPackageManagerInternal = packageManagerInternal;
        mParserSupplier = parserSupplier;
        mEvaluationEngine = evaluationEngine;
        mIntegrityFileManager = integrityFileManager;
        mHandler = handler;

@@ -330,7 +325,7 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
                                + " installers "
                                + allowedInstallers);
            }
            IntegrityCheckResult result = mEvaluationEngine.evaluate(appInstallMetadata);
            IntegrityCheckResult result = IntegrityCheckResult.allow();
            if (!result.getMatchedRules().isEmpty() || DEBUG_INTEGRITY_COMPONENT) {
                Slog.i(
                        TAG,
+0 −85
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.integrity.engine;

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

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.integrity.IntegrityFileManager;
import com.android.server.integrity.model.IntegrityCheckResult;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * The engine used to evaluate rules against app installs.
 *
 * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
 * to allow/block that install.
 */
public class RuleEvaluationEngine {
    private static final String TAG = "RuleEvaluation";

    // The engine for loading rules, retrieving metadata for app installs, and evaluating app
    // installs against rules.
    private static RuleEvaluationEngine sRuleEvaluationEngine;

    private final IntegrityFileManager mIntegrityFileManager;

    @VisibleForTesting
    RuleEvaluationEngine(IntegrityFileManager integrityFileManager) {
        mIntegrityFileManager = integrityFileManager;
    }

    /** Provide a singleton instance of the rule evaluation engine. */
    public static synchronized RuleEvaluationEngine getRuleEvaluationEngine() {
        if (sRuleEvaluationEngine == null) {
            return new RuleEvaluationEngine(IntegrityFileManager.getInstance());
        }
        return sRuleEvaluationEngine;
    }

    /**
     * Load, and match the list of rules against an app install metadata.
     *
     * @param appInstallMetadata Metadata of the app to be installed, and to evaluate the rules
     *                           against.
     * @return result of the integrity check
     */
    public IntegrityCheckResult evaluate(
            AppInstallMetadata appInstallMetadata) {
        List<Rule> rules = loadRules(appInstallMetadata);
        return IntegrityCheckResult.allow();
    }

    private List<Rule> loadRules(AppInstallMetadata appInstallMetadata) {
        if (!mIntegrityFileManager.initialized()) {
            Slog.w(TAG, "Integrity rule files are not available.");
            return Collections.emptyList();
        }

        try {
            return mIntegrityFileManager.readRules(appInstallMetadata);
        } catch (Exception e) {
            Slog.e(TAG, "Error loading rules.", e);
            return new ArrayList<>();
        }
    }
}
+0 −118
Original line number Diff line number Diff line
@@ -69,7 +69,6 @@ import androidx.test.InstrumentationRegistry;
import com.android.internal.R;
import com.android.internal.pm.parsing.PackageParser2;
import com.android.server.compat.PlatformCompat;
import com.android.server.integrity.engine.RuleEvaluationEngine;
import com.android.server.integrity.model.IntegrityCheckResult;
import com.android.server.pm.parsing.TestPackageParser2;
import com.android.server.testutils.TestUtils;
@@ -138,7 +137,6 @@ public class AppIntegrityManagerServiceImplTest {
    @Mock PlatformCompat mPlatformCompat;
    @Mock Context mMockContext;
    @Mock Resources mMockResources;
    @Mock RuleEvaluationEngine mRuleEvaluationEngine;
    @Mock IntegrityFileManager mIntegrityFileManager;
    @Mock Handler mHandler;

@@ -176,7 +174,6 @@ public class AppIntegrityManagerServiceImplTest {
                        mMockContext,
                        mPackageManagerInternal,
                        mParserSupplier,
                        mRuleEvaluationEngine,
                        mIntegrityFileManager,
                        mHandler);

@@ -306,91 +303,6 @@ public class AppIntegrityManagerServiceImplTest {
        assertEquals(PACKAGE_MIME_TYPE, intentFilterCaptor.getValue().getDataType(0));
    }

    @Test
    public void handleBroadcast_correctArgs() throws Exception {
        allowlistUsAsRuleProvider();
        makeUsSystemApp();
        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext)
                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
        Intent intent = makeVerificationIntent();
        when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow());

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

        ArgumentCaptor<AppInstallMetadata> metadataCaptor =
                ArgumentCaptor.forClass(AppInstallMetadata.class);
        verify(mRuleEvaluationEngine).evaluate(metadataCaptor.capture());
        AppInstallMetadata appInstallMetadata = metadataCaptor.getValue();
        assertEquals(PACKAGE_NAME, appInstallMetadata.getPackageName());
        assertThat(appInstallMetadata.getAppCertificates()).containsExactly(APP_CERT);
        assertEquals(INSTALLER_SHA256, appInstallMetadata.getInstallerName());
        // we cannot check installer cert because it seems to be device specific.
        assertEquals(VERSION_CODE, appInstallMetadata.getVersionCode());
        assertFalse(appInstallMetadata.isPreInstalled());
        // Asserting source stamp not present.
        assertFalse(appInstallMetadata.isStampPresent());
        assertFalse(appInstallMetadata.isStampVerified());
        assertFalse(appInstallMetadata.isStampTrusted());
        assertNull(appInstallMetadata.getStampCertificateHash());
        // These are hardcoded in the test apk android manifest
        Map<String, String> allowedInstallers =
                appInstallMetadata.getAllowedInstallersAndCertificates();
        assertEquals(2, allowedInstallers.size());
        assertEquals(PLAY_STORE_CERT, allowedInstallers.get(PLAY_STORE_PKG));
        assertEquals(INSTALLER_CERTIFICATE_NOT_EVALUATED, allowedInstallers.get(ADB_INSTALLER));
    }

    @Test
    public void handleBroadcast_correctArgs_multipleCerts() throws Exception {
        allowlistUsAsRuleProvider();
        makeUsSystemApp();
        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext)
                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
        Intent intent = makeVerificationIntent();
        intent.setDataAndType(Uri.fromFile(mTestApkTwoCerts), PACKAGE_MIME_TYPE);
        when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow());

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

        ArgumentCaptor<AppInstallMetadata> metadataCaptor =
                ArgumentCaptor.forClass(AppInstallMetadata.class);
        verify(mRuleEvaluationEngine).evaluate(metadataCaptor.capture());
        AppInstallMetadata appInstallMetadata = metadataCaptor.getValue();
        assertThat(appInstallMetadata.getAppCertificates())
                .containsExactly(DUMMY_APP_TWO_CERTS_CERT_1, DUMMY_APP_TWO_CERTS_CERT_2);
    }

    @Test
    public void handleBroadcast_correctArgs_sourceStamp() throws Exception {
        allowlistUsAsRuleProvider();
        makeUsSystemApp();
        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext)
                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
        Intent intent = makeVerificationIntent();
        intent.setDataAndType(Uri.fromFile(mTestApkSourceStamp), PACKAGE_MIME_TYPE);
        when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow());

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

        ArgumentCaptor<AppInstallMetadata> metadataCaptor =
                ArgumentCaptor.forClass(AppInstallMetadata.class);
        verify(mRuleEvaluationEngine).evaluate(metadataCaptor.capture());
        AppInstallMetadata appInstallMetadata = metadataCaptor.getValue();
        assertTrue(appInstallMetadata.isStampPresent());
        assertTrue(appInstallMetadata.isStampVerified());
        assertTrue(appInstallMetadata.isStampTrusted());
        assertEquals(SOURCE_STAMP_CERTIFICATE_HASH, appInstallMetadata.getStampCertificateHash());
    }

    @Test
    public void handleBroadcast_allow() throws Exception {
        allowlistUsAsRuleProvider();
@@ -400,7 +312,6 @@ public class AppIntegrityManagerServiceImplTest {
        verify(mMockContext)
                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
        Intent intent = makeVerificationIntent();
        when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow());

        broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
        runJobInHandler();
@@ -410,32 +321,6 @@ public class AppIntegrityManagerServiceImplTest {
                        1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
    }

    @Test
    public void handleBroadcast_reject() throws Exception {
        allowlistUsAsRuleProvider();
        makeUsSystemApp();
        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext)
                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
        when(mRuleEvaluationEngine.evaluate(any()))
                .thenReturn(
                        IntegrityCheckResult.deny(
                                Arrays.asList(
                                        new Rule(
                                                new AtomicFormula.BooleanAtomicFormula(
                                                        AtomicFormula.PRE_INSTALLED, false),
                                                Rule.DENY))));
        Intent intent = makeVerificationIntent();

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

        verify(mPackageManagerInternal)
                .setIntegrityVerificationResult(
                        1, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
    }

    @Test
    public void handleBroadcast_notInitialized() throws Exception {
        allowlistUsAsRuleProvider();
@@ -446,7 +331,6 @@ public class AppIntegrityManagerServiceImplTest {
        verify(mMockContext)
                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
        Intent intent = makeVerificationIntent();
        when(mRuleEvaluationEngine.evaluate(any())).thenReturn(IntegrityCheckResult.allow());

        broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
        runJobInHandler();
@@ -467,8 +351,6 @@ public class AppIntegrityManagerServiceImplTest {
        verify(mMockContext, atLeastOnce())
                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
        Intent intent = makeVerificationIntent(TEST_FRAMEWORK_PACKAGE);
        when(mRuleEvaluationEngine.evaluate(any()))
                .thenReturn(IntegrityCheckResult.deny(/* rule= */ null));

        broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
        runJobInHandler();
+0 −192
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.integrity.engine;

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.IntegrityFormula;
import android.content.integrity.Rule;

import com.android.server.integrity.IntegrityFileManager;
import com.android.server.integrity.model.IntegrityCheckResult;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@RunWith(JUnit4.class)
public class RuleEvaluationEngineTest {

    private static final String INSTALLER_1 = "installer1";
    private static final String INSTALLER_1_CERT = "installer1_cert";
    private static final String INSTALLER_2 = "installer2";
    private static final String INSTALLER_2_CERT = "installer2_cert";

    private static final String RANDOM_INSTALLER = "random";
    private static final String RANDOM_INSTALLER_CERT = "random_cert";

    @Mock
    private IntegrityFileManager mIntegrityFileManager;

    private RuleEvaluationEngine mEngine;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mEngine = new RuleEvaluationEngine(mIntegrityFileManager);

        when(mIntegrityFileManager.readRules(any())).thenReturn(Collections.singletonList(new Rule(
                IntegrityFormula.Installer.notAllowedByManifest(), Rule.DENY)));

        when(mIntegrityFileManager.initialized()).thenReturn(true);
    }

    @Test
    public void testAllowedInstallers_empty() {
        AppInstallMetadata appInstallMetadata1 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificates(Collections.singletonList(INSTALLER_1_CERT))
                        .build();
        AppInstallMetadata appInstallMetadata2 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_2)
                        .setInstallerCertificates(Collections.singletonList(INSTALLER_2_CERT))
                        .build();
        AppInstallMetadata appInstallMetadata3 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(RANDOM_INSTALLER)
                        .setInstallerCertificates(Collections.singletonList(RANDOM_INSTALLER_CERT))
                        .build();

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

    @Test
    public void testAllowedInstallers_oneElement() {
        Map<String, String> allowedInstallers =
                Collections.singletonMap(INSTALLER_1, INSTALLER_1_CERT);

        AppInstallMetadata appInstallMetadata1 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setInstallerCertificates(Collections.singletonList(INSTALLER_1_CERT))
                        .setAllowedInstallersAndCert(allowedInstallers)
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata1).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata2 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(RANDOM_INSTALLER)
                        .setAllowedInstallersAndCert(allowedInstallers)
                        .setInstallerCertificates(Collections.singletonList(INSTALLER_1_CERT))
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata2).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata3 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setAllowedInstallersAndCert(allowedInstallers)
                        .setInstallerCertificates(Collections.singletonList(RANDOM_INSTALLER_CERT))
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata3).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata4 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setAllowedInstallersAndCert(allowedInstallers)
                        .setInstallerCertificates(Collections.singletonList(RANDOM_INSTALLER_CERT))
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata4).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
    }

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

        AppInstallMetadata appInstallMetadata1 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setAllowedInstallersAndCert(allowedInstallers)
                        .setInstallerCertificates(Collections.singletonList(INSTALLER_1_CERT))
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata1).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata2 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_2)
                        .setAllowedInstallersAndCert(allowedInstallers)
                        .setInstallerCertificates(Collections.singletonList(INSTALLER_2_CERT))
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata2).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata3 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_1)
                        .setAllowedInstallersAndCert(allowedInstallers)
                        .setInstallerCertificates(Collections.singletonList(INSTALLER_2_CERT))
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata3).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);

        AppInstallMetadata appInstallMetadata4 =
                getAppInstallMetadataBuilder()
                        .setInstallerName(INSTALLER_2)
                        .setAllowedInstallersAndCert(allowedInstallers)
                        .setInstallerCertificates(Collections.singletonList(INSTALLER_1_CERT))
                        .build();
        assertThat(mEngine.evaluate(appInstallMetadata4).getEffect())
                .isEqualTo(IntegrityCheckResult.Effect.ALLOW);
    }

    /** Returns a builder with all fields filled with some placeholder data. */
    private AppInstallMetadata.Builder getAppInstallMetadataBuilder() {
        return new AppInstallMetadata.Builder()
                .setPackageName("abc")
                .setAppCertificates(Collections.singletonList("abc"))
                .setAppCertificateLineage(Collections.singletonList("abc"))
                .setInstallerCertificates(Collections.singletonList("abc"))
                .setInstallerName("abc")
                .setVersionCode(-1)
                .setIsPreInstalled(true);
    }
}