diff options
| author | 2020-01-29 12:18:10 +0000 | |
|---|---|---|
| committer | 2020-01-29 12:21:14 +0000 | |
| commit | 84f7c3fb53737dd470cbdb06c4a24890bc7ccaaa (patch) | |
| tree | c3fe65aba6c054964e835e86f40428b0d3b8e683 | |
| parent | aff240adccfd3d5db4477822fd0ac71604ecbd09 (diff) | |
Implement the necessary methods for identifying the DENY / FORCE_ALLOW
causes for logging purposes.
Bug: 147095027
Test: atest frameworks/base/core/tests/coretests/src/android/content/integrity/
Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/integrity
Change-Id: Id502287b22fc54fd1585f81b313fb466d1f8442c
10 files changed, 307 insertions, 31 deletions
diff --git a/core/java/android/content/integrity/AtomicFormula.java b/core/java/android/content/integrity/AtomicFormula.java index 4c10a8f7ad38..76007e67798d 100644 --- a/core/java/android/content/integrity/AtomicFormula.java +++ b/core/java/android/content/integrity/AtomicFormula.java @@ -205,6 +205,16 @@ public abstract class AtomicFormula extends IntegrityFormula { } @Override + public boolean isAppCertificateFormula() { + return false; + } + + @Override + public boolean isInstallerFormula() { + return false; + } + + @Override public String toString() { if (mValue == null || mOperator == null) { return String.format("(%s)", keyToString(getKey())); @@ -375,6 +385,16 @@ public abstract class AtomicFormula extends IntegrityFormula { } @Override + public boolean isAppCertificateFormula() { + return getKey() == APP_CERTIFICATE; + } + + @Override + public boolean isInstallerFormula() { + return getKey() == INSTALLER_NAME || getKey() == INSTALLER_CERTIFICATE; + } + + @Override public String toString() { if (mValue == null || mIsHashedValue == null) { return String.format("(%s)", keyToString(getKey())); @@ -531,6 +551,16 @@ public abstract class AtomicFormula extends IntegrityFormula { } @Override + public boolean isAppCertificateFormula() { + return false; + } + + @Override + public boolean isInstallerFormula() { + return false; + } + + @Override public String toString() { if (mValue == null) { return String.format("(%s)", keyToString(getKey())); diff --git a/core/java/android/content/integrity/CompoundFormula.java b/core/java/android/content/integrity/CompoundFormula.java index 56061df21388..14b1197d7f45 100644 --- a/core/java/android/content/integrity/CompoundFormula.java +++ b/core/java/android/content/integrity/CompoundFormula.java @@ -131,6 +131,16 @@ public final class CompoundFormula extends IntegrityFormula implements Parcelabl } @Override + public boolean isAppCertificateFormula() { + return getFormulas().stream().anyMatch(formula -> formula.isAppCertificateFormula()); + } + + @Override + public boolean isInstallerFormula() { + return getFormulas().stream().anyMatch(formula -> formula.isInstallerFormula()); + } + + @Override public String toString() { StringBuilder sb = new StringBuilder(); if (mFormulas.size() == 1) { diff --git a/core/java/android/content/integrity/IntegrityFormula.java b/core/java/android/content/integrity/IntegrityFormula.java index 0660f93e9f01..8505d32e3f02 100644 --- a/core/java/android/content/integrity/IntegrityFormula.java +++ b/core/java/android/content/integrity/IntegrityFormula.java @@ -136,6 +136,21 @@ public abstract class IntegrityFormula { public abstract @Tag boolean matches(AppInstallMetadata appInstallMetadata); /** + * Returns true when the formula (or one of its atomic formulas) has app certificate as key. + * + * @hide + */ + public abstract @Tag boolean isAppCertificateFormula(); + + /** + * Returns true when the formula (or one of its atomic formulas) has installer package name + * or installer certificate as key. + * + * @hide + */ + public abstract @Tag boolean isInstallerFormula(); + + /** * Write an {@link IntegrityFormula} to {@link android.os.Parcel}. * * <p>This helper method is needed because non-final class/interface are not allowed to be diff --git a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java index 7328f35790da..bf782034c8f1 100644 --- a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java +++ b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.testng.Assert.expectThrows; import android.content.integrity.AtomicFormula.BooleanAtomicFormula; +import android.content.integrity.AtomicFormula.LongAtomicFormula; import android.content.integrity.AtomicFormula.StringAtomicFormula; import android.os.Parcel; @@ -114,8 +115,8 @@ public class AtomicFormulaTest { @Test public void testValidAtomicFormula_longValue() { - AtomicFormula.LongAtomicFormula longAtomicFormula = - new AtomicFormula.LongAtomicFormula( + LongAtomicFormula longAtomicFormula = + new LongAtomicFormula( AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1); assertThat(longAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE); @@ -151,7 +152,7 @@ public class AtomicFormulaTest { expectThrows( IllegalArgumentException.class, () -> - new AtomicFormula.LongAtomicFormula( + new LongAtomicFormula( AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1)); assertThat(e.getMessage()).matches( "Key PACKAGE_NAME cannot be used with LongAtomicFormula"); @@ -182,14 +183,14 @@ public class AtomicFormulaTest { @Test public void testParcelUnparcel_int() { - AtomicFormula.LongAtomicFormula formula = - new AtomicFormula.LongAtomicFormula( + LongAtomicFormula formula = + new LongAtomicFormula( AtomicFormula.VERSION_CODE, AtomicFormula.GT, 1); Parcel p = Parcel.obtain(); formula.writeToParcel(p, 0); p.setDataPosition(0); - AtomicFormula.LongAtomicFormula newFormula = - AtomicFormula.LongAtomicFormula.CREATOR.createFromParcel(p); + LongAtomicFormula newFormula = + LongAtomicFormula.CREATOR.createFromParcel(p); assertThat(newFormula).isEqualTo(formula); } @@ -211,7 +212,7 @@ public class AtomicFormulaTest { Exception e = expectThrows( IllegalArgumentException.class, - () -> new AtomicFormula.LongAtomicFormula(/* key= */ -1, + () -> new LongAtomicFormula(/* key= */ -1, AtomicFormula.EQ, /* value= */0)); assertThat(e.getMessage()).matches("Unknown key: -1"); } @@ -222,7 +223,7 @@ public class AtomicFormulaTest { expectThrows( IllegalArgumentException.class, () -> - new AtomicFormula.LongAtomicFormula( + new LongAtomicFormula( AtomicFormula.VERSION_CODE, /* operator= */ -1, /* value= */ 0)); assertThat(e.getMessage()).matches("Unknown operator: -1"); @@ -252,10 +253,59 @@ public class AtomicFormulaTest { assertThat(stringAtomicFormula.matches(appInstallMetadata)).isFalse(); } + + @Test + public void testIsAppCertificateFormula_string_true() { + StringAtomicFormula stringAtomicFormula = + new StringAtomicFormula( + AtomicFormula.APP_CERTIFICATE, "cert", /* isHashedValue= */false); + + assertThat(stringAtomicFormula.isAppCertificateFormula()).isTrue(); + } + + @Test + public void testIsAppCertificateFormula_string_false() { + StringAtomicFormula stringAtomicFormula = + new StringAtomicFormula( + AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ + false); + + assertThat(stringAtomicFormula.isAppCertificateFormula()).isFalse(); + } + + @Test + public void testIsInstallerFormula_string_false() { + StringAtomicFormula stringAtomicFormula = + new StringAtomicFormula( + AtomicFormula.APP_CERTIFICATE, "cert", /* isHashedValue= */false); + + assertThat(stringAtomicFormula.isInstallerFormula()).isFalse(); + } + + @Test + public void testIsInstallerFormula_string_installerName_true() { + StringAtomicFormula stringAtomicFormula = + new StringAtomicFormula( + AtomicFormula.INSTALLER_NAME, + "com.test.installer", + /* isHashedValue= */false); + + assertThat(stringAtomicFormula.isInstallerFormula()).isTrue(); + } + + @Test + public void testIsInstallerFormula_string_installerCertificate_true() { + StringAtomicFormula stringAtomicFormula = + new StringAtomicFormula( + AtomicFormula.INSTALLER_CERTIFICATE, "cert", /* isHashedValue= */false); + + assertThat(stringAtomicFormula.isInstallerFormula()).isTrue(); + } + @Test public void testFormulaMatches_long_eq_true() { - AtomicFormula.LongAtomicFormula longAtomicFormula = - new AtomicFormula.LongAtomicFormula( + LongAtomicFormula longAtomicFormula = + new LongAtomicFormula( AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0); AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder().setVersionCode(0).build(); @@ -265,8 +315,8 @@ public class AtomicFormulaTest { @Test public void testFormulaMatches_long_eq_false() { - AtomicFormula.LongAtomicFormula longAtomicFormula = - new AtomicFormula.LongAtomicFormula( + LongAtomicFormula longAtomicFormula = + new LongAtomicFormula( AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0); AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder().setVersionCode(1).build(); @@ -276,8 +326,8 @@ public class AtomicFormulaTest { @Test public void testFormulaMatches_long_gt_true() { - AtomicFormula.LongAtomicFormula longAtomicFormula = - new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, + LongAtomicFormula longAtomicFormula = + new LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, 0); AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder().setVersionCode(1).build(); @@ -287,8 +337,8 @@ public class AtomicFormulaTest { @Test public void testFormulaMatches_long_gt_false() { - AtomicFormula.LongAtomicFormula longAtomicFormula = - new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, + LongAtomicFormula longAtomicFormula = + new LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, 1); AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder().setVersionCode(0).build(); @@ -298,8 +348,8 @@ public class AtomicFormulaTest { @Test public void testFormulaMatches_long_gte_true() { - AtomicFormula.LongAtomicFormula longAtomicFormula = - new AtomicFormula.LongAtomicFormula( + LongAtomicFormula longAtomicFormula = + new LongAtomicFormula( AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1); AppInstallMetadata appInstallMetadata1 = @@ -313,8 +363,8 @@ public class AtomicFormulaTest { @Test public void testFormulaMatches_long_gte_false() { - AtomicFormula.LongAtomicFormula longAtomicFormula = - new AtomicFormula.LongAtomicFormula( + LongAtomicFormula longAtomicFormula = + new LongAtomicFormula( AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1); AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder().setVersionCode(0).build(); @@ -323,6 +373,24 @@ public class AtomicFormulaTest { } @Test + public void testIsAppCertificateFormula_long_false() { + LongAtomicFormula longAtomicFormula = + new AtomicFormula.LongAtomicFormula( + AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1); + + assertThat(longAtomicFormula.isAppCertificateFormula()).isFalse(); + } + + @Test + public void testIsInstallerFormula_long_false() { + LongAtomicFormula longAtomicFormula = + new LongAtomicFormula( + AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1); + + assertThat(longAtomicFormula.isInstallerFormula()).isFalse(); + } + + @Test public void testFormulaMatches_bool_true() { BooleanAtomicFormula boolFormula = new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true); @@ -342,6 +410,22 @@ public class AtomicFormulaTest { assertThat(boolFormula.matches(appInstallMetadata)).isFalse(); } + @Test + public void testIsAppCertificateFormula_bool_false() { + BooleanAtomicFormula boolFormula = + new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true); + + assertThat(boolFormula.isAppCertificateFormula()).isFalse(); + } + + @Test + public void testIsInstallerFormula_bool_false() { + BooleanAtomicFormula boolFormula = + new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true); + + assertThat(boolFormula.isInstallerFormula()).isFalse(); + } + /** Returns a builder with all fields filled with some dummy data. */ private AppInstallMetadata.Builder getAppInstallMetadataBuilder() { return new AppInstallMetadata.Builder() diff --git a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java index 4054c4916089..f47dfdd191fb 100644 --- a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java +++ b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java @@ -225,6 +225,63 @@ public class CompoundFormulaTest { assertThat(compoundFormula.matches(appInstallMetadata)).isFalse(); } + @Test + public void testIsAppCertificateFormula_false() { + CompoundFormula compoundFormula = + new CompoundFormula( + CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)); + + assertThat(compoundFormula.isAppCertificateFormula()).isFalse(); + } + + @Test + public void testIsAppCertificateFormula_true() { + AtomicFormula appCertFormula = + new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, + "app.cert", /* isHashed= */false); + CompoundFormula compoundFormula = + new CompoundFormula( + CompoundFormula.AND, + Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2, appCertFormula)); + + assertThat(compoundFormula.isAppCertificateFormula()).isTrue(); + } + + @Test + public void testIsInstallerFormula_false() { + CompoundFormula compoundFormula = + new CompoundFormula( + CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)); + + assertThat(compoundFormula.isInstallerFormula()).isFalse(); + } + + @Test + public void testIsInstallerFormula_installerName_true() { + AtomicFormula installerNameFormula = + new AtomicFormula.StringAtomicFormula(AtomicFormula.INSTALLER_NAME, + "com.test.installer", /* isHashed= */false); + CompoundFormula compoundFormula = + new CompoundFormula( + CompoundFormula.AND, + Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2, installerNameFormula)); + + assertThat(compoundFormula.isInstallerFormula()).isTrue(); + } + + @Test + public void testIsInstallerFormula_installerCertificate_true() { + AtomicFormula installerCertificateFormula = + new AtomicFormula.StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE, + "cert", /* isHashed= */false); + CompoundFormula compoundFormula = + new CompoundFormula( + CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2, + installerCertificateFormula)); + + assertThat(compoundFormula.isInstallerFormula()).isTrue(); + } + /** Returns a builder with all fields filled with some dummy data. */ private AppInstallMetadata.Builder getAppInstallMetadataBuilder() { return new AppInstallMetadata.Builder() diff --git a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java index d6dd0464c145..1b605c7c430c 100644 --- a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java +++ b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java @@ -96,20 +96,14 @@ public final class IntegrityCheckResult { } } - /** - * Returns true when the {@code Effect.DENY} result is caused by an app certificate mismatch. - */ + /** Returns true when the {@code mEffect} is caused by an app certificate mismatch. */ public boolean isCausedByAppCertRule() { - // TODO(b/147095027): implement this. - return true; + return mRuleList.stream().anyMatch(rule -> rule.getFormula().isAppCertificateFormula()); } - /** - * Returns true when the {@code Effect.DENY} result is caused by an installer rule. - */ + /** Returns true when the {@code mEffect} is caused by an installer rule. */ public boolean isCausedByInstallerRule() { - // TODO(b/147095027): implement this. - return true; + return mRuleList.stream().anyMatch(rule -> rule.getFormula().isInstallerFormula()); } } diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java index 9cc9f10e2c82..ec1423958f8f 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java @@ -19,6 +19,7 @@ package com.android.server.integrity.model; import static com.google.common.truth.Truth.assertThat; import android.content.integrity.AtomicFormula; +import android.content.integrity.CompoundFormula; import android.content.integrity.Rule; import android.util.StatsLog; @@ -26,6 +27,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.util.Arrays; import java.util.Collections; @RunWith(JUnit4.class) @@ -76,4 +78,58 @@ public class IntegrityCheckResultTest { assertThat(denyResult.getLoggingResponse()) .isEqualTo(StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED); } + + @Test + public void isDenyCausedByAppCertificate() { + String packageName = "com.test.deny"; + String appCert = "app-cert"; + Rule failedRule = + new Rule( + new CompoundFormula( + CompoundFormula.AND, + Arrays.asList( + new AtomicFormula.StringAtomicFormula( + AtomicFormula.PACKAGE_NAME, packageName), + new AtomicFormula.StringAtomicFormula( + AtomicFormula.APP_CERTIFICATE, appCert))), + Rule.DENY); + Rule otherFailedRule = + new Rule( + new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, + AtomicFormula.EQ, 12), + Rule.DENY); + + IntegrityCheckResult denyResult = + IntegrityCheckResult.deny(Arrays.asList(failedRule, otherFailedRule)); + + assertThat(denyResult.isCausedByAppCertRule()).isTrue(); + assertThat(denyResult.isCausedByInstallerRule()).isFalse(); + } + + @Test + public void isDenyCausedByInstaller() { + String packageName = "com.test.deny"; + String appCert = "app-cert"; + Rule failedRule = + new Rule( + new CompoundFormula( + CompoundFormula.AND, + Arrays.asList( + new AtomicFormula.StringAtomicFormula( + AtomicFormula.PACKAGE_NAME, packageName), + new AtomicFormula.StringAtomicFormula( + AtomicFormula.INSTALLER_CERTIFICATE, appCert))), + Rule.DENY); + Rule otherFailedRule = + new Rule( + new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, + AtomicFormula.EQ, 12), + Rule.DENY); + + IntegrityCheckResult denyResult = + IntegrityCheckResult.deny(Arrays.asList(failedRule, otherFailedRule)); + + assertThat(denyResult.isCausedByAppCertRule()).isFalse(); + assertThat(denyResult.isCausedByInstallerRule()).isTrue(); + } } diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java index f3da286585fd..b3d949395d5c 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java @@ -872,6 +872,16 @@ public class RuleBinarySerializerTest { } @Override + public boolean isAppCertificateFormula() { + return false; + } + + @Override + public boolean isInstallerFormula() { + return false; + } + + @Override public int hashCode() { return super.hashCode(); } diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java index 038ab7ff0c35..913aff7daaa9 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java @@ -299,6 +299,16 @@ public class RuleIndexingDetailsIdentifierTest { } @Override + public boolean isAppCertificateFormula() { + return false; + } + + @Override + public boolean isInstallerFormula() { + return false; + } + + @Override public int hashCode() { return super.hashCode(); } diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java index 6558cd538638..b7825356654c 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java @@ -543,6 +543,16 @@ public class RuleXmlSerializerTest { } @Override + public boolean isAppCertificateFormula() { + return false; + } + + @Override + public boolean isInstallerFormula() { + return false; + } + + @Override public int hashCode() { return super.hashCode(); } |