/*
 * 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 <string.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));
}
