diff options
| author | 2019-12-18 13:36:49 +0000 | |
|---|---|---|
| committer | 2019-12-18 13:36:49 +0000 | |
| commit | 10197b127a9563ba51b7a4f99d95be5f1b12e172 (patch) | |
| tree | 2308aec5237a5c542728efde8bee2d5a3201077f | |
| parent | 32e4875f6b9a23f95d1ef38f9fd7c3efe575883b (diff) | |
| parent | 30749c8f86e9c0a715ee06fd968496ead594c941 (diff) | |
Merge "Extend integrity component indexing type identification to also return the key value that the indexing will be done with."
| -rw-r--r-- | services/core/java/com/android/server/integrity/serializer/RuleIndexTypeIdentifier.java | 117 | ||||
| -rw-r--r-- | services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java | 67 | ||||
| -rw-r--r-- | services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java | 127 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java (renamed from services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexTypeIdentifierTest.java) | 37 |
4 files changed, 216 insertions, 132 deletions
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexTypeIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexTypeIdentifier.java deleted file mode 100644 index 4d3961df6092..000000000000 --- a/services/core/java/com/android/server/integrity/serializer/RuleIndexTypeIdentifier.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.serializer; - -import android.annotation.IntDef; -import android.content.integrity.AtomicFormula; -import android.content.integrity.CompoundFormula; -import android.content.integrity.Formula; -import android.content.integrity.Rule; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** A helper class for identifying the indexing type of a given rule. */ -public class RuleIndexTypeIdentifier { - - static final int NOT_INDEXED = 0; - static final int PACKAGE_NAME_INDEXED = 1; - static final int APP_CERTIFICATE_INDEXED = 2; - - /** Represents which indexed file the rule should be located. */ - @IntDef( - value = { - NOT_INDEXED, - PACKAGE_NAME_INDEXED, - APP_CERTIFICATE_INDEXED - }) - @Retention(RetentionPolicy.SOURCE) - public @interface IndexType { - } - - /** Determines the indexing file type that a given rule should be located at. */ - public static int getIndexType(Rule rule) { - if (rule == null) { - throw new IllegalArgumentException("Indexing type cannot be determined for null rule."); - } - return getIndexType(rule.getFormula()); - } - - private static int getIndexType(Formula formula) { - if (formula == null) { - throw new IllegalArgumentException( - "Indexing type cannot be determined for null formula."); - } - - switch (formula.getTag()) { - case Formula.COMPOUND_FORMULA_TAG: - return getIndexTypeForCompoundFormula((CompoundFormula) formula); - case Formula.STRING_ATOMIC_FORMULA_TAG: - return getIndexTypeForAtomicStringFormula((AtomicFormula) formula); - case Formula.INT_ATOMIC_FORMULA_TAG: - case Formula.BOOLEAN_ATOMIC_FORMULA_TAG: - // Package name and app certificate related formulas are string atomic formulas. - return NOT_INDEXED; - default: - throw new IllegalArgumentException( - String.format("Invalid formula tag type: %s", formula.getTag())); - } - } - - private static int getIndexTypeForCompoundFormula(CompoundFormula compoundFormula) { - int connector = compoundFormula.getConnector(); - List<Formula> formulas = compoundFormula.getFormulas(); - - switch (connector) { - case CompoundFormula.NOT: - // Having a NOT operator in the indexing messes up the indexing; e.g., deny - // installation if app certificate is NOT X (should not be indexed with app cert - // X). We will not keep these rules indexed. - return NOT_INDEXED; - case CompoundFormula.AND: - case CompoundFormula.OR: - Set<Integer> indexingTypesForAllFormulas = - formulas.stream() - .map(formula -> getIndexType(formula)) - .collect(Collectors.toSet()); - if (indexingTypesForAllFormulas.contains(PACKAGE_NAME_INDEXED)) { - return PACKAGE_NAME_INDEXED; - } else if (indexingTypesForAllFormulas.contains(APP_CERTIFICATE_INDEXED)) { - return APP_CERTIFICATE_INDEXED; - } else { - return NOT_INDEXED; - } - default: - return NOT_INDEXED; - } - } - - private static int getIndexTypeForAtomicStringFormula(AtomicFormula atomicFormula) { - switch (atomicFormula.getKey()) { - case AtomicFormula.PACKAGE_NAME: - return PACKAGE_NAME_INDEXED; - case AtomicFormula.APP_CERTIFICATE: - return APP_CERTIFICATE_INDEXED; - default: - return NOT_INDEXED; - } - } -} - diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java new file mode 100644 index 000000000000..dd871e2bbe6c --- /dev/null +++ b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java @@ -0,0 +1,67 @@ +/* + * 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.serializer; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** Holds the indexing type and indexing key of a given formula. */ +class RuleIndexingDetails { + + static final int NOT_INDEXED = 0; + static final int PACKAGE_NAME_INDEXED = 1; + static final int APP_CERTIFICATE_INDEXED = 2; + + /** Represents which indexed file the rule should be located. */ + @IntDef( + value = { + NOT_INDEXED, + PACKAGE_NAME_INDEXED, + APP_CERTIFICATE_INDEXED + }) + @Retention(RetentionPolicy.SOURCE) + public @interface IndexType { + } + + private @IndexType int mIndexType; + private String mRuleKey; + + /** Constructor without a ruleKey for {@code NOT_INDEXED}. */ + RuleIndexingDetails(@IndexType int indexType) { + this.mIndexType = indexType; + this.mRuleKey = null; + } + + /** Constructor with a ruleKey for indexed rules. */ + RuleIndexingDetails(@IndexType int indexType, String ruleKey) { + this.mIndexType = indexType; + this.mRuleKey = ruleKey; + } + + /** Returns the indexing type for the rule. */ + @IndexType + public int getIndexType() { + return mIndexType; + } + + /** Returns the identified rule key. */ + public String getRuleKey() { + return mRuleKey; + } +} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java new file mode 100644 index 000000000000..4aabb1c87b34 --- /dev/null +++ b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java @@ -0,0 +1,127 @@ +/* + * 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.serializer; + +import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED; +import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED; +import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED; + +import android.content.integrity.AtomicFormula; +import android.content.integrity.CompoundFormula; +import android.content.integrity.Formula; +import android.content.integrity.Rule; + +import java.util.List; +import java.util.Optional; + +/** A helper class for identifying the indexing type and key of a given rule. */ +class RuleIndexingDetailsIdentifier { + + /** Determines the indexing type and key for a given rule. */ + public static RuleIndexingDetails getIndexingDetails(Rule rule) { + if (rule == null) { + throw new IllegalArgumentException("Indexing type cannot be determined for null rule."); + } + return getIndexingDetails(rule.getFormula()); + } + + private static RuleIndexingDetails getIndexingDetails(Formula formula) { + if (formula == null) { + throw new IllegalArgumentException( + "Indexing type cannot be determined for null formula."); + } + + switch (formula.getTag()) { + case Formula.COMPOUND_FORMULA_TAG: + return getIndexingDetailsForCompoundFormula((CompoundFormula) formula); + case Formula.STRING_ATOMIC_FORMULA_TAG: + return getIndexingDetailsForAtomicStringFormula((AtomicFormula) formula); + case Formula.INT_ATOMIC_FORMULA_TAG: + case Formula.BOOLEAN_ATOMIC_FORMULA_TAG: + // Package name and app certificate related formulas are string atomic formulas. + return new RuleIndexingDetails(NOT_INDEXED); + default: + throw new IllegalArgumentException( + String.format("Invalid formula tag type: %s", formula.getTag())); + } + } + + private static RuleIndexingDetails getIndexingDetailsForCompoundFormula( + CompoundFormula compoundFormula) { + int connector = compoundFormula.getConnector(); + List<Formula> formulas = compoundFormula.getFormulas(); + + switch (connector) { + case CompoundFormula.AND: + case CompoundFormula.OR: + // If there is a package name related atomic rule, return package name indexed. + Optional<RuleIndexingDetails> packageNameRule = + formulas.stream() + .map(formula -> getIndexingDetails(formula)) + .filter(ruleIndexingDetails -> ruleIndexingDetails.getIndexType() + == PACKAGE_NAME_INDEXED) + .findAny(); + if (packageNameRule.isPresent()) { + return packageNameRule.get(); + } + + // If there is an app certificate related atomic rule but no package name related + // atomic rule, return app certificate indexed. + Optional<RuleIndexingDetails> appCertificateRule = + formulas.stream() + .map(formula -> getIndexingDetails(formula)) + .filter(ruleIndexingDetails -> ruleIndexingDetails.getIndexType() + == APP_CERTIFICATE_INDEXED) + .findAny(); + if (appCertificateRule.isPresent()) { + return appCertificateRule.get(); + } + + // Do not index when there is not package name or app certificate indexing. + return new RuleIndexingDetails(NOT_INDEXED); + default: + // Having a NOT operator in the indexing messes up the indexing; e.g., deny + // installation if app certificate is NOT X (should not be indexed with app cert + // X). We will not keep these rules indexed. + // Also any other type of unknown operators will not be indexed. + return new RuleIndexingDetails(NOT_INDEXED); + } + } + + private static RuleIndexingDetails getIndexingDetailsForAtomicStringFormula( + AtomicFormula atomicFormula) { + switch (atomicFormula.getKey()) { + case AtomicFormula.PACKAGE_NAME: + return new RuleIndexingDetails(PACKAGE_NAME_INDEXED, + getValueFromAtomicRuleString(atomicFormula.toString())); + case AtomicFormula.APP_CERTIFICATE: + return new RuleIndexingDetails(APP_CERTIFICATE_INDEXED, + getValueFromAtomicRuleString(atomicFormula.toString())); + default: + return new RuleIndexingDetails(NOT_INDEXED); + } + } + + // The AtomRule API does not allow direct access to the {@link AtomicFormula} value. However, + // this value is printed as "(%s %s %s)" where the last %s stands for the value. This method + // parses the last. + private static String getValueFromAtomicRuleString(String ruleString) { + // TODO (b/145488708): Make an API change and get rid of this trick. + return ruleString.split(" ")[2].split("[)]")[0]; + } +} + diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexTypeIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java index 18b91b0b1009..abb1787cede5 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexTypeIdentifierTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java @@ -16,6 +16,9 @@ package com.android.server.integrity.serializer; +import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED; +import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED; +import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED; import static com.android.server.testutils.TestUtils.assertExpectException; import static com.google.common.truth.Truth.assertThat; @@ -34,9 +37,9 @@ import org.junit.runners.JUnit4; import java.util.Arrays; -/** Unit tests for {@link RuleIndexTypeIdentifier}. */ +/** Unit tests for {@link RuleIndexingDetailsIdentifier}. */ @RunWith(JUnit4.class) -public class RuleIndexTypeIdentifierTest { +public class RuleIndexingDetailsIdentifierTest { @Test public void getIndexType_nullRule() { @@ -46,7 +49,7 @@ public class RuleIndexTypeIdentifierTest { IllegalArgumentException.class, /* expectedExceptionMessageRegex= */ "Indexing type cannot be determined for null rule.", - () -> RuleIndexTypeIdentifier.getIndexType(rule)); + () -> RuleIndexingDetailsIdentifier.getIndexingDetails(rule)); } @Test @@ -56,7 +59,7 @@ public class RuleIndexTypeIdentifierTest { assertExpectException( IllegalArgumentException.class, /* expectedExceptionMessageRegex= */ "Invalid formula tag type.", - () -> RuleIndexTypeIdentifier.getIndexType(rule)); + () -> RuleIndexingDetailsIdentifier.getIndexingDetails(rule)); } @Test @@ -78,8 +81,10 @@ public class RuleIndexTypeIdentifierTest { /* isHashedValue= */ false))), Rule.DENY); - assertThat(RuleIndexTypeIdentifier.getIndexType(rule)) - .isEqualTo(RuleIndexTypeIdentifier.PACKAGE_NAME_INDEXED); + RuleIndexingDetails result = RuleIndexingDetailsIdentifier.getIndexingDetails(rule); + + assertThat(result.getIndexType()).isEqualTo(PACKAGE_NAME_INDEXED); + assertThat(result.getRuleKey()).isEqualTo(packageName); } @Test @@ -101,8 +106,11 @@ public class RuleIndexTypeIdentifierTest { /* isHashedValue= */ false))), Rule.DENY); - assertThat(RuleIndexTypeIdentifier.getIndexType(rule)) - .isEqualTo(RuleIndexTypeIdentifier.APP_CERTIFICATE_INDEXED); + + RuleIndexingDetails result = RuleIndexingDetailsIdentifier.getIndexingDetails(rule); + + assertThat(result.getIndexType()).isEqualTo(APP_CERTIFICATE_INDEXED); + assertThat(result.getRuleKey()).isEqualTo(appCertificate); } @Test @@ -124,8 +132,8 @@ public class RuleIndexTypeIdentifierTest { /* isHashedValue= */ false))), Rule.DENY); - assertThat(RuleIndexTypeIdentifier.getIndexType(rule)) - .isEqualTo(RuleIndexTypeIdentifier.NOT_INDEXED); + assertThat(RuleIndexingDetailsIdentifier.getIndexingDetails(rule).getIndexType()) + .isEqualTo(NOT_INDEXED); } @Test @@ -145,8 +153,8 @@ public class RuleIndexTypeIdentifierTest { appVersion))), Rule.DENY); - assertThat(RuleIndexTypeIdentifier.getIndexType(rule)) - .isEqualTo(RuleIndexTypeIdentifier.NOT_INDEXED); + assertThat(RuleIndexingDetailsIdentifier.getIndexingDetails(rule).getIndexType()) + .isEqualTo(NOT_INDEXED); } @Test @@ -171,8 +179,8 @@ public class RuleIndexTypeIdentifierTest { /* isHashedValue= */ false))))), Rule.DENY); - assertThat(RuleIndexTypeIdentifier.getIndexType(rule)) - .isEqualTo(RuleIndexTypeIdentifier.NOT_INDEXED); + assertThat(RuleIndexingDetailsIdentifier.getIndexingDetails(rule).getIndexType()) + .isEqualTo(NOT_INDEXED); } private Formula getInvalidFormula() { @@ -215,4 +223,3 @@ public class RuleIndexTypeIdentifierTest { }; } } - |