am 65374948: Add Exynos vulnerability tests.

* commit '6537494848b04482ed3127072310b01017fe62e6':
  Add Exynos vulnerability tests.
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index 40f844c..f36be9d 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -22,6 +22,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
+LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsSecurityTestCases
@@ -31,3 +33,5 @@
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
new file mode 100644
index 0000000..ee185c5
--- /dev/null
+++ b/tests/tests/security/jni/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 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 := libctssecurity_jni
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+		CtsSecurityJniOnLoad.cpp \
+		android_security_cts_CharDeviceTest.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
new file mode 100644
index 0000000..045581f
--- /dev/null
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 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 <jni.h>
+#include <stdio.h>
+
+extern int register_android_security_cts_CharDeviceTest(JNIEnv*);
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+    JNIEnv *env = NULL;
+
+    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    if (register_android_security_cts_CharDeviceTest(env)) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/security/jni/android_security_cts_CharDeviceTest.cpp b/tests/tests/security/jni/android_security_cts_CharDeviceTest.cpp
new file mode 100644
index 0000000..9aea4b3
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_CharDeviceTest.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2012 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 <jni.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <cutils/log.h>
+
+#define PHYS_OFFSET 0x40000000
+
+/*
+ * Native methods used by
+ * cts/tests/tests/permission/src/android/security/cts/CharDeviceTest.java
+ */
+
+jboolean android_security_cts_CharDeviceTest_doExynosWriteTest(JNIEnv* env, jobject thiz)
+{
+    int page_size = sysconf(_SC_PAGE_SIZE);
+    int length = page_size * page_size;
+    int fd = open("/dev/exynos-mem", O_RDWR);
+    if (fd < 0) {
+        return true;
+    }
+
+    char *addr = (char *)
+        mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, PHYS_OFFSET);
+
+    if (addr == MAP_FAILED) {
+        goto done2;
+    }
+
+    /*
+     * In the presence of the vulnerability, the code below will
+     * cause the device to crash, because we're scribbling all
+     * over kernel memory
+     */
+
+    int i;
+    for (i = 0; i < length; i++) {
+        addr[i] = 'A';
+    }
+    usleep(100000);
+
+done1:
+    munmap(addr, length);
+done2:
+    close(fd);
+    return true;
+}
+
+jboolean android_security_cts_CharDeviceTest_doExynosReadTest(JNIEnv* env, jobject thiz)
+{
+    const char *MAGIC_STRING = "KHAAAAN!!! EXYNOS!!!";
+
+    jboolean ret = true;
+    int page_size = sysconf(_SC_PAGE_SIZE);
+    int length = page_size * page_size;
+    int fd = open("/dev/exynos-mem", O_RDONLY);
+    if (fd < 0) {
+        return true;
+    }
+
+    char *addr = (char *)
+        mmap(NULL, length, PROT_READ, MAP_SHARED, fd, PHYS_OFFSET);
+
+    if (addr == MAP_FAILED) {
+        goto done2;
+    }
+
+    // Throw the magic string into the kernel ring buffer. Once
+    // there, we shouldn't be able to access it.
+    ALOGE("%s", MAGIC_STRING);
+
+    // Now see if we can scan kernel memory, looking for our magic
+    // string.  If we find it, return false.
+    int i;
+    for (i = 0; i < (length - strlen(MAGIC_STRING)); i++) {
+        if (strncmp(&addr[i], MAGIC_STRING, strlen(MAGIC_STRING)) == 0) {
+            ret = false;
+            break;
+        }
+    }
+
+done1:
+    munmap(addr, length);
+done2:
+    close(fd);
+    return ret;
+}
+
+static JNINativeMethod gMethods[] = {
+    {  "doExynosWriteTest", "()Z",
+            (void *) android_security_cts_CharDeviceTest_doExynosWriteTest },
+    {  "doExynosReadTest", "()Z",
+            (void *) android_security_cts_CharDeviceTest_doExynosReadTest },
+};
+
+int register_android_security_cts_CharDeviceTest(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/security/cts/CharDeviceTest");
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/security/src/android/security/cts/CharDeviceTest.java b/tests/tests/security/src/android/security/cts/CharDeviceTest.java
new file mode 100644
index 0000000..88d36c8
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CharDeviceTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 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 junit.framework.TestCase;
+
+public class CharDeviceTest extends TestCase {
+
+    static {
+        System.loadLibrary("ctssecurity_jni");
+    }
+
+    /**
+     * Detect Exynos 4xxx rooting vuln.
+     *
+     * Reference: http://forum.xda-developers.com/showthread.php?t=2048511
+     */
+    public void testExynosRootingVuln() throws Exception {
+        assertTrue(doExynosWriteTest());
+    }
+
+    /**
+     * Detect Exynos 4xxx kernel memory leak to userspace.
+     *
+     * Reference: http://forum.xda-developers.com/showthread.php?t=2048511
+     */
+    public void testExynosKernelMemoryRead() throws Exception {
+        assertTrue(doExynosReadTest());
+    }
+
+    /**
+     * @return true iff the device does not have the exynos rooting
+     *     vulnerability.  If the device has the rooting vulnerability,
+     *     this method will cause the device to crash and this function
+     *     will never return.
+     */
+    private static native boolean doExynosWriteTest();
+
+    /**
+     * @return true iff the device does not provide read-access to kernel memory
+     */
+    private static native boolean doExynosReadTest();
+}