diff options
| -rw-r--r-- | services/core/java/com/android/server/integrity/engine/RuleEvaluator.java | 26 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java | 53 |
2 files changed, 78 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java index a4bf2b045361..641650557f4c 100644 --- a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java +++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java @@ -37,6 +37,9 @@ final class RuleEvaluator { /** * Match the list of rules against an app install metadata. * + * <p>Rules must be in disjunctive normal form (DNF). A rule should contain AND'ed formulas + * only. All rules are OR'ed together by default. + * * @param rules The list of rules to evaluate. * @param appInstallMetadata Metadata of the app to be installed, and to evaluate the rules * against. @@ -45,7 +48,7 @@ final class RuleEvaluator { */ static Rule evaluateRules(List<Rule> rules, AppInstallMetadata appInstallMetadata) { for (Rule rule : rules) { - if (isMatch(rule, appInstallMetadata)) { + if (isConjunctionOfFormulas(rule.getFormula()) && isMatch(rule, appInstallMetadata)) { return rule; } } @@ -99,4 +102,25 @@ final class RuleEvaluator { return false; } + + private static boolean isConjunctionOfFormulas(Formula formula) { + if (formula == null) { + return false; + } + if (isAtomicFormula(formula)) { + return true; + } + OpenFormula openFormula = (OpenFormula) formula; + return openFormula.getConnector() == OpenFormula.Connector.AND + && openFormula.getFormulas().stream().allMatch(RuleEvaluator::isAtomicFormula); + } + + private static boolean isAtomicFormula(Formula formula) { + if (formula instanceof AtomicFormula) { + return true; + } + OpenFormula openFormula = (OpenFormula) formula; + return openFormula.getConnector() == OpenFormula.Connector.NOT + && openFormula.getFormulas().get(0) instanceof AtomicFormula; + } } diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java index 1fcd0ef07410..baf1ed00c7b5 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java @@ -127,4 +127,57 @@ public class RuleEvaluatorTest { assertEquals(rule1, matchedRule); } + + @Test + public void testMatchRules_validForm() { + OpenFormula openFormula = new OpenFormula(OpenFormula.Connector.AND, Arrays.asList( + new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ, + PACKAGE_NAME_1), + new AtomicFormula(AtomicFormula.Key.APP_CERTIFICATE, + AtomicFormula.Operator.EQ, + APP_CERTIFICATE))); + Rule rule = new Rule( + openFormula, Rule.Effect.DENY); + + Rule matchedRule = RuleEvaluator.evaluateRules(Collections.singletonList(rule), + APP_INSTALL_METADATA); + + assertEquals(rule, matchedRule); + } + + @Test + public void testMatchRules_ruleNotInDNF() { + OpenFormula openFormula = new OpenFormula(OpenFormula.Connector.OR, Arrays.asList( + new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ, + PACKAGE_NAME_1), + new AtomicFormula(AtomicFormula.Key.APP_CERTIFICATE, + AtomicFormula.Operator.EQ, + APP_CERTIFICATE))); + Rule rule = new Rule( + openFormula, Rule.Effect.DENY); + + Rule matchedRule = RuleEvaluator.evaluateRules(Collections.singletonList(rule), + APP_INSTALL_METADATA); + + assertEquals(Rule.EMPTY, matchedRule); + } + + @Test + public void testMatchRules_openFormulaWithNot() { + OpenFormula openSubFormula = new OpenFormula(OpenFormula.Connector.AND, Arrays.asList( + new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ, + PACKAGE_NAME_2), + new AtomicFormula(AtomicFormula.Key.APP_CERTIFICATE, + AtomicFormula.Operator.EQ, + APP_CERTIFICATE))); + OpenFormula openFormula = new OpenFormula(OpenFormula.Connector.NOT, + Collections.singletonList(openSubFormula)); + Rule rule = new Rule( + openFormula, Rule.Effect.DENY); + + Rule matchedRule = RuleEvaluator.evaluateRules(Collections.singletonList(rule), + APP_INSTALL_METADATA); + + assertEquals(Rule.EMPTY, matchedRule); + } } |