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

Commit 35e8f367 authored by Omer Nebil Yaveroglu's avatar Omer Nebil Yaveroglu
Browse files

Put size limits on the number of rules that can be

pushed through a verifier.

Bug: 147865065
Test: atest FrameworksServicesTests:RuleBinarySerializerTest
Change-Id: I7767fe9bc18761988b8ef19578d491183904984b
parent aa6e9586
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@ import java.util.stream.Collectors;

/** A helper class to serialize rules from the {@link Rule} model to Binary representation. */
public class RuleBinarySerializer implements RuleSerializer {
    static final int TOTAL_RULE_SIZE_LIMIT = 200000;
    static final int INDEXED_RULE_SIZE_LIMIT = 100000;
    static final int NONINDEXED_RULE_SIZE_LIMIT = 1000;

    // Get the byte representation for a list of rules.
    @Override
@@ -79,10 +82,23 @@ public class RuleBinarySerializer implements RuleSerializer {
            OutputStream indexingFileOutputStream)
            throws RuleSerializeException {
        try {
            if (rules == null) {
                throw new IllegalArgumentException("Null rules cannot be serialized.");
            }

            if (rules.size() > TOTAL_RULE_SIZE_LIMIT) {
                throw new IllegalArgumentException("Too many rules provided.");
            }

            // Determine the indexing groups and the order of the rules within each indexed group.
            Map<Integer, Map<String, List<Rule>>> indexedRules =
                    RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);

            // Validate the rule blocks are not larger than expected limits.
            verifySize(indexedRules.get(PACKAGE_NAME_INDEXED), INDEXED_RULE_SIZE_LIMIT);
            verifySize(indexedRules.get(APP_CERTIFICATE_INDEXED), INDEXED_RULE_SIZE_LIMIT);
            verifySize(indexedRules.get(NOT_INDEXED), NONINDEXED_RULE_SIZE_LIMIT);

            // Serialize the rules.
            ByteTrackedOutputStream ruleFileByteTrackedOutputStream =
                    new ByteTrackedOutputStream(rulesFileOutputStream);
@@ -112,6 +128,16 @@ public class RuleBinarySerializer implements RuleSerializer {
        }
    }

    private void verifySize(Map<String, List<Rule>> ruleListMap, int ruleSizeLimit) {
        int totalRuleCount =
                ruleListMap.values().stream()
                        .map(list -> list.size())
                        .collect(Collectors.summingInt(Integer::intValue));
        if (totalRuleCount > ruleSizeLimit) {
            throw new IllegalArgumentException("Too many rules provided in the indexing group.");
        }
    }

    private void serializeRuleFileMetadata(
            Optional<Integer> formatVersion, ByteTrackedOutputStream outputStream)
            throws IOException {
+130 −4
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@ import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BIT
import static com.android.server.integrity.model.IndexingFileConstants.END_INDEXING_KEY;
import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE;
import static com.android.server.integrity.model.IndexingFileConstants.START_INDEXING_KEY;
import static com.android.server.integrity.serializer.RuleBinarySerializer.INDEXED_RULE_SIZE_LIMIT;
import static com.android.server.integrity.serializer.RuleBinarySerializer.NONINDEXED_RULE_SIZE_LIMIT;
import static com.android.server.integrity.utils.TestUtils.getBits;
import static com.android.server.integrity.utils.TestUtils.getBytes;
import static com.android.server.integrity.utils.TestUtils.getValueBits;
@@ -112,8 +114,7 @@ public class RuleBinarySerializerTest {

        assertExpectException(
                RuleSerializeException.class,
                /* expectedExceptionMessageRegex= */ "Index buckets cannot be created for null"
                        + " rule list.",
                /* expectedExceptionMessageRegex= */ "Null rules cannot be serialized.",
                () -> binarySerializer.serialize(null, /* formatVersion= */ Optional.empty()));
    }

@@ -618,6 +619,131 @@ public class RuleBinarySerializerTest {
                .isEqualTo(expectedIndexingOutputStream.toByteArray());
    }

    @Test
    public void testBinaryString_totalRuleSizeLimitReached() {
        int ruleCount = INDEXED_RULE_SIZE_LIMIT - 1;
        String packagePrefix = "package.name.";
        String appCertificatePrefix = "app.cert.";
        String installerNamePrefix = "installer.";

        // Create the rule set with more rules than the system can handle in total.
        List<Rule> ruleList = new ArrayList();
        for (int count = 0; count < ruleCount; count++) {
            ruleList.add(
                    getRuleWithPackageNameAndSampleInstallerName(
                            String.format("%s%04d", packagePrefix, count)));
        }
        for (int count = 0; count < ruleCount; count++) {
            ruleList.add(
                    getRuleWithAppCertificateAndSampleInstallerName(
                            String.format("%s%04d", appCertificatePrefix, count)));
        }
        for (int count = 0; count < NONINDEXED_RULE_SIZE_LIMIT - 1; count++) {
            ruleList.add(
                    getNonIndexedRuleWithInstallerName(
                            String.format("%s%04d", installerNamePrefix, count)));
        }

        // Serialize the rules.
        ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream();
        ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream();
        RuleSerializer binarySerializer = new RuleBinarySerializer();

        assertExpectException(
                RuleSerializeException.class,
                "Too many rules provided",
                () ->
                        binarySerializer.serialize(
                                ruleList,
                                /* formatVersion= */ Optional.empty(),
                                ruleOutputStream,
                                indexingOutputStream));
    }

    @Test
    public void testBinaryString_tooManyPackageNameIndexedRules() {
        String packagePrefix = "package.name.";

        // Create a rule set with too many package name indexed rules.
        List<Rule> ruleList = new ArrayList();
        for (int count = 0; count < INDEXED_RULE_SIZE_LIMIT + 1; count++) {
            ruleList.add(
                    getRuleWithPackageNameAndSampleInstallerName(
                            String.format("%s%04d", packagePrefix, count)));
        }

        // Serialize the rules.
        ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream();
        ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream();
        RuleSerializer binarySerializer = new RuleBinarySerializer();

        assertExpectException(
                RuleSerializeException.class,
                "Too many rules provided in the indexing group.",
                () ->
                        binarySerializer.serialize(
                                ruleList,
                                /* formatVersion= */ Optional.empty(),
                                ruleOutputStream,
                                indexingOutputStream));
    }

    @Test
    public void testBinaryString_tooManyAppCertificateIndexedRules() {
        String appCertificatePrefix = "app.cert.";

        // Create a rule set with too many app certificate indexed rules.
        List<Rule> ruleList = new ArrayList();
        for (int count = 0; count < INDEXED_RULE_SIZE_LIMIT + 1; count++) {
            ruleList.add(
                    getRuleWithAppCertificateAndSampleInstallerName(
                            String.format("%s%04d", appCertificatePrefix, count)));
        }

        // Serialize the rules.
        ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream();
        ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream();
        RuleSerializer binarySerializer = new RuleBinarySerializer();

        assertExpectException(
                RuleSerializeException.class,
                "Too many rules provided in the indexing group.",
                () ->
                        binarySerializer.serialize(
                                ruleList,
                                /* formatVersion= */ Optional.empty(),
                                ruleOutputStream,
                                indexingOutputStream));
    }

    @Test
    public void testBinaryString_tooManyNonIndexedRules() {
        String installerNamePrefix = "installer.";

        // Create a rule set with too many unindexed rules.
        List<Rule> ruleList = new ArrayList();
        for (int count = 0; count < NONINDEXED_RULE_SIZE_LIMIT + 1; count++) {
            ruleList.add(
                    getNonIndexedRuleWithInstallerName(
                            String.format("%s%04d", installerNamePrefix, count)));
        }

        // Serialize the rules.
        ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream();
        ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream();
        RuleSerializer binarySerializer = new RuleBinarySerializer();

        assertExpectException(
                RuleSerializeException.class,
                "Too many rules provided in the indexing group.",
                () ->
                        binarySerializer.serialize(
                                ruleList,
                                /* formatVersion= */ Optional.empty(),
                                ruleOutputStream,
                                indexingOutputStream));
    }

    private Rule getRuleWithPackageNameAndSampleInstallerName(String packageName) {
        return new Rule(
                new CompoundFormula(